zoukankan      html  css  js  c++  java
  • MVC5 学习整理

    一、概述

    MVC简介:

    •       模型(Model) “数据模型”(Model)用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。“模型”有对数据直接访问的权力,例如对数据库的访问。“模型”不依赖“视图”和“控制器”,也就是说,模型不关心它会被如何显示或是如何被操作。但是模型中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制,那些用于监视此模型的视图必须事先在此模型上注册,从而,视图可以了解在数据模型上发生的改变。

    •       视图(View) 视图层能够实现数据有目的的显示(理论上,这不是必需的)。在视图中一般没有程序上的逻辑。为了实现视图上的刷新功能,视图需要访问它监视的数据模型(Model),因此应该事先在被它监视的数据那里注册。

    •       控制器(Controller) 控制器起到不同层面间的组织作用,用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据模型上的改变。

    MVC网站的访问流程:

    •       1. 当第一个请求从客户端发起的时候,首先执行的是Global.asax中的Application_Start()方法来完成一些初始化工作,其中重要的一步是RegisterRoutes方法,这个方法指定了如何将url映射到具体的方法上,稍后详解。

    •       2. 根据第一步中指定的映射表生成一个RouteData对象,利用这个对象来创建一个RequestContext对象。

    •        3. MvcRouteHandler创建一个MvcHandler,并将RequestContext对象传给MvcHandler。

    •        4. MvcHandler对象利用RequestContext对象确定一个IControllerFactory对象来创建Controller对象。

    •        5. MvcHandler对象调用Controller对象的Execute()方法。

    •        6. Controller的ControolerActionInvoker对象决定调用controller的哪个具体的action方法。

    •        7. Action方法接受用户参数,执行方法,返回一个Result类型的对象。

    二、MODEL

    定义

     使用@model关键字可以定义一个Action里所对应的一个模型(经常可以叫他实体类),

    其实是对动态变量进行实例化,这样就可以直接在cshtml文件中调用“Model”变量。

    而这个模型的实例,需要通过Controller进行传输,如果没有则“Model”将为null。

     模型可以是一个实体类,也可以是一个列表实例,字典对象都可以进行定义,但是和

    Controller中的Action传回来的实例一定要一样,否则将会出现错误。例如我们获取

    用户实例,并且在页面上呈现用户的具体信息,这样就可以将用户实例返回给前台

    验证标记整理:

    Model类中可以添加的验证标记:

     1. 必填字段

    [Required]

    public string FirstName { get; set; }

    2. 字段长度

    至多n位:

    [StringLength(160)]

    public string FirstName { get; set; }

    要求至少n位:

    [StringLength(160, MinimumLength=3)]

    public string FirstName { get; set; }

    3. 正则验证

    [RegularExpression(@”[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}”)]

    public string Email { get; set; }

    4. 范围

    [Range(35,44)]

    public int Age { get; set; }

    小数的情况:

    [Range(typeof(decimal), “0.00”, “49.99”)]

    public decimal Price { get; set; }

    5. 服务端参与的验证 

    [Remote(“CheckUserName”, “Account”)]

    public string UserName { get; set; }

    然后在AccountController里指定一个CheckUserName方法:

    public JsonResult CheckUserName(stringusername)

    {

       var result = Membership.FindUsersByName(username).Count == 0;

       return Json(result, JsonRequestBehavior.AllowGet);

    }

    6. 比较

    [RegularExpression(@”[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}”)]

    public string Email { get; set; }

    [Compare(“Email”)]

    public string EmailConfirm { get; set; }

    7. 自定义错误消息 

    正则:

    [RegularExpression(@”[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}”,

                       ErrorMessage=”Email doesn’tlook like a valid email address.”)]

    public string Email { get; set; }

    普通文本:

    [Required(ErrorMessage=”Your last name isrequired”)]

    [StringLength(160, ErrorMessage=”Your lastname is too long”)]

    public string LastName { get; set; }

    占位符:

    [Required(ErrorMessage=”Your {0} isrequired.”)]

    [StringLength(160, ErrorMessage=”{0} is toolong.”)]

    public string LastName { get; set; }

    三、View与Controller

    1、母版页

    Shared/_Layout.cshtml

    2、HtmlHelper

    ActionLink

    @Html.ActionLink("Text", "Index", "Home", new { page = 1 }, new { id = "link1" })

    解释为:

    <a href="/?page=1" id="link1">Text</a>

    RouteLink

    其实就是用一个新建立的RouteValueDictionary的对象(new{}所实例化的对象将会等价转换为RouteValueDictionary)来替原来的Action,Controller字符串的单独指定。

    示例:@Html.RouteLink("Text",new { action = "index", page = 1 }, new { id="link1"})

    可通过路由名称指定指向某路由路径。

    示例:@Html.RouteLink("关于","about", new { page = 1 }, new { id = "link1" })

    其中about为路由名称

    表单

    表单两种方式:

    1、<form action="@Url.Action("Index","Home")"method="post"></form>

    2、@using(Html.BeginForm("Index","Movies",FormMethod.Get)){}

    3、绑定下拉框示例:

       @Html.DropDownList("movieGenre","All")

    3、urlHtml

    <a href='<%=Url.Action("DemoAction","DemoController", new{id=2,category=5 },"https")%>' title="">指定传输协议生成URL</a><br/>

    解释为:<ahref='https://localhost/DemoController/DemoAction?id=2&category=5'title="">指定传输协议生成URL</a><br />

    4、Controller

    从Model获取数据,然后通过ViewData传递给View数据

    可以使用不同的View呈现数据

    ActionResult的其它返回值:JsonResult、RedirectResult

    PartialView(自定义控件)、View方法

    ViewData、TempData传值

    ViewData只能在当前Action中有效 

    TempData可以类似于Session一样到其它页面仍然存在,但只限一页的访问

    TempData一般用于临时的缓存内容或抛出错误页面时传递错误信息

      

    5、验证

    ValidateAntiForgeryToken 特性,这个特性用来阻止伪造的请求,它和视图(ViewsMoviesEdit.cshtml)中的@Html.AntiForgeryToken() 是成对出现的。

    显示验证错误信息

    @Html.ValidationSummary(true, "",new { @class = "text-danger" })

    6、ajax提交

    1、显示当前页面层 

    2、提交数据到controller中方法如下图代码 

    3、ajaxHelper

    1、Ajax异步请求ContentController

    ContentController直接以字符串形式返回实例的内容,在Index.cshtml中使用ActionLink,如下:

    @Ajax.ActionLink("AjaxContentController","getEntry", new { id = item.Id }, new AjaxOptions { HttpMethod ="Post", UpdateTargetId = "detailsID", InsertionMode =InsertionMode.Replace })

    相应的Controller:

    public string getEntry(int id = 0) {

                GuestbookEntryentry = _db.Entries.First(c => c.Id == id);

                returnentry.Details;

    }

      2、使用Json格式返回

    @Ajax.ActionLink("AjaxJsonController","JsonDetails", new { id = item.Id }, new AjaxOptions { HttpMethod ="Post", InsertionMode = InsertionMode.Replace, OnSuccess = "Show();"})

    相应的Controller:

    public ActionResult JsonDetails(int id = 0)

            {

                GuestbookEntryentry = _db.Entries.First(c => c.Id == id);

                return Json(entry,JsonRequestBehavior.AllowGet);

            }

    注意:在使用Json格式返回数据时,由于安全原因,只接收Post请求,因此在这里使用JsonRequestBehavior.AllowGet来允许Get方式请求。

    同时需要在Index.cshtml中添加请求成功的相应函数Show:

    <script type="text/javascript">

            function Show(data) {

               $("#detailsID").html("姓名:" + data.Name+ " 消息:" + data.Message);

            }

    </script>

    四、路由配置 

    路由配置:

    1、多个区域中增加多个member,而每个member中存在一个路由

    2、在项目中可以设置一个总路由指定到某个命名空间。然后在每个member区域设置单独路由。

    MapRoute是RouteCollection的扩展方法,同时还有IngnoreRoute,而Add则是实例方法,相对来说要使用Add来调用比较复杂(包含刚才提到的5大属性),而MapRoute则相对简洁。

    Add

    routes.Add(new Route("blog/{action}/{author}", 
                     new RouteValueDictionary { {"action", "show" }, {"author", "miracle"} },
                     new MvcRouteHandler()));

    MapRoute

    routes.MapRoute(
          "Article", // 路由名称
          "blog/{action}/{author}", // 带有参数的 URL
          new { controller = "Home", action = "show", author = "miracle" } 
    );

    路由解析处理:

    当用户输入URL地址发送请求时,UrlRoutingModule类就会到路由表(RouteTable)中解析与请求匹配的路由,然后将该路由分发到路由处理程序(IRouteHandler),并连同RequestContext一起再次分发到Mvc处理程序(IHttpHandler),定位相关的控制器并执行相关的动作实现输出。以下的整个过程的示意图。

    在传统的Web站点中使用路由(一般情况下用户将传统站点转化为MVC站点的项目迁移过渡)。主要包含以下两个步骤:

    1、常见实现IRouteHandler接口的WebFormRouteHandler类,返回实现IHttpHandler接口的实例化对象(实际上任何一个Page都是一个IHttpHandler实例对象)。

     public class WebFormRouteHandler : IRouteHandler

    {

        public stringVirtualPath { get; private set; }

        //初始化虚拟路径

        publicWebFormRouteHandler(string virtualPath)

        {

            this.VirtualPath= virtualPath;

        }

        public IHttpHandler GetHttpHandler(RequestContext requestContext)

        {

            //创建实例化的页面对象

            var page =BuildManager.CreateInstanceFromVirtualPath(VirtualPath, typeof(Page)) as IHttpHandler;

            return page;

        }

    }

     

    2、配置全局应用程序类(Global.asax),实现路由的映射。

    routes.MapMvcAttributeRoutes(); //Attribute路由注册

    AreaRegistration.RegisterAllAreas();//区域路由注册

    注:增加区域之后,防止路由重复,需在默认路由中为命名空间赋值。

    Attribute路由

    1、路由定义和 Action 放在一起:

    [Route("Home/Index/{id}")]

    public ActionResult Index() {... }

    与通用路由是否可以一起使用待验证,已经验证,可以一起使用。以Attribute这里为主。

    2、URL可选参数和默认值

    [Route("Home/Index/{id?}")]

    匹配//Home/Index或者/Home/Index/id

    //匹配:/books/lang

    //匹配:/books/lang/en

    //匹配:/books/lang/he

    //如果URL不传递 lang 参数,则lang的值为“en” 

    [Route("books/lang/{lang=en}")]

    3、前缀

    //匹配:/Home

    [Route("Home")]

    publicActionResult Index() { ... }

    //匹配:/ Home/5

    [Route("Home/{id}")]

    publicActionResult Show(int id) { ... }

    //匹配:/ Home/5/edit

    [Route("Home/{id}/edit")]

    publicActionResult Edit(int id) { ... } 

    或者在controller前面增加属性[RoutePrefix("Home")]

    4、默认路由 

    [RoutePrefix("promotions")]

    [Route("{action=index}")]

    默认promotions,action为index 

    ActionResult前面增加[Route]则覆盖默认路由。

    5、路由约束

    路由约束可以让你指定参数的类型以及范围等,格式为:{参数:约束},举例如下:

    // 匹配: /users/5

    [Route("users/{id:int}"]

    // 这里约束了参数“id”必须为整数类型 

    publicActionResult GetUserById(int id) { ... }

    下面是支持的路由约束列表:

    Constraint

    Description

    Example

    alpha

    Matches uppercase or lowercase Latin alphabet characters (a-z, A-Z)

    {x:alpha}

    bool

    Matches a Boolean value.

    {x:bool}

    datetime

    Matches a DateTime value.

    {x:datetime}

    decimal

    Matches a decimal value.

    {x:decimal}

    double

    Matches a 64-bit floating-point value.

    {x:double}

    float

    Matches a 32-bit floating-point value.

    {x:float}

    guid

    Matches a GUID value.

    {x:guid}

    int

    Matches a 32-bit integer value.

    {x:int}

    length

    Matches a string with the specified length or within a specified range of lengths.

    {x:length(6)} {x:length(1,20)}

    long

    Matches a 64-bit integer value.

    {x:long}

    max

    Matches an integer with a maximum value.

    {x:max(10)}

    maxlength

    Matches a string with a maximum length.

    {x:maxlength(10)}

    min

    Matches an integer with a minimum value.

    {x:min(10)}

    minlength

    Matches a string with a minimum length.

    {x:minlength(10)}

    range

    Matches an integer within a range of values.

    {x:range(10,50)}

    regex

    Matches a regular expression.

    {x:regex(^d{3}-d{3}-d{4}$)}

    你可以在一个参数后面应用多个约束,用冒号分隔它们,如下:

    // 匹配: /users/5

    // 但是不匹配 /users/10000000000 因为id的值已经超过了int.MaxValue,

    // 也不匹配 /users/0 因为后面有个min(1)约束,id 的值必须大于等于 1.

    [Route("users/{id:int:min(1)}")]

    publicActionResult GetUserById(int id) { ... }

    6、自定义约束

    看上例

    7、路由名称 

    [Route("menu",Name = "mainmenu")]

    publicActionResult MainMenu() { ... }

    可以使用Url.RouteUrl 来生成相应的 URL:

    <ahref="@Url.RouteUrl("mainmenu")">Main menu</a>

    8、Areas区域 

    Area概念对组织大型Web应用程序很有帮助,在Attribute路由中当然少不了对它的支持,只要使用 [RouteArea],就可以把 Controller 归属到某一个 Area 下

    删除Area 下的AreaRegistration 类 

    [RouteArea("Admin")]

    [RoutePrefix("menu")]

    [Route("{action}")]

    publicclass MenuController : Controller

    {

    //匹配:/admin/menu/login

    publicActionResult Login() { ... }

    }

    五、扩展

    1、实现对HTMLHelper的扩展。 

    新建文件夹:Extensions,文件夹Extensions中添加自定义扩展。

    使用时,view页面必须加入:@using MVCMovie.Extensions;//自定义。

    页面引用如:@Html.QINLabel("male", "男") 

    示例:

    public static string Label(this HtmlHelperhelper, string name, string value)

    {

       return string.Format("<labelfor='{0}'>{1}</label><br />", name, value);

    2、AjaxHelper的扩展

    新增扩展类

    控制器

    public class AjaxHelperExtController :Controller

        {

           //

           // GET: /AjaxHelperExt/ 

           public ActionResult AjaxHelperExt()

           {

               return View();

           } 

           public ActionResult GetTime()

           {

               return Content("Now Time:" + DateTime.Now.ToString());

           }

        }

    最后在jquery.unobtrusive-ajax.js里面加上TextBox的Keyup事件绑定 

    $("input[type=text][data-ajax=true]").live("keyup",function (evt) {

           asyncRequest(this, { type: "GET" ,data: [{ name:$(this).attr('name'), value: $(this).val()}] });

       });

    调用

    <divid="divTime"></div> 

    @Ajax.Textbox("search",

       new AjaxOptions

        {

           Url = @Url.Action("GetTime") ,

           UpdateTargetId = "divTime",

           InsertionMode = InsertionMode.Replace

       },

    new { size = 50 })

    注:同时需要在页面中引入MicrosoftAjax.js,MicrosoftMvcAjax.js

    在web.config中增加client side validation and unobtrusive javascript 两个配置

    <addkey="ClientValidationEnabled" value="true" />

    <addkey="UnobtrusiveJavaScriptEnabled" value="true" />

    原文来自 http://www.cnblogs.com/gxlinhai/p/4261471.html

  • 相关阅读:
    关于自动分裂的思考 | Solrex 杨文博的博客,记录我的生活、技术、思想和梦想
    在STL中,map按值来排序的实现方法_永不言弃是生命的基调!_百度空间
    C/C++学习路线(教材推荐)_Hello World!_百度空间
    Google C++ Style中允许使用的Boost库(1) 程序即人生 博客频道 CSDN.NET
    STL中map按值(value)排序
    程序即人生 » 移动平台现在可用的C++ 11特性
    开发者应该了解的 12 款 Eclipse 插件 编程语言 ITeye资讯
    Lisp的给力特性(V.S. Python3) 第二篇 程序即人生 博客频道 CSDN.NET
    Solidot | 地球上有多少Java程序员?
    在STL中,map按值来排序的实现方法
  • 原文地址:https://www.cnblogs.com/-lzx/p/5235011.html
Copyright © 2011-2022 走看看