• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

如鹏网学习笔记(十五)ASP.NETMVC核心基础笔记

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

一、ASP.Net MVC简介

  1,什么是ASP.NET MVC?
    HttpHandler是ASP.net的底层机制,如果直接使用HttpHandler进行开发难度比较大、工作量大。因此提供了ASP.Net MVC、
    ASP.Net WebForm等高级封装的框架,简化开发,他们的底层仍然是HttpHandler、HttpRequest等
    例如:ASP.NET MVC的核心类仍然是实现了IHttpHandler接口的MVCHandler

  2,ASP.NET WebForm和ASP.NET MVC的关系?
    两者都是对HttpHandler的封装框架,ASP.NET MVC的思想,更适合现代项目的开发,因此会逐步取代WebForm

  3,为什么ASP.NET MVC更好
    程序员有更强的掌控力,不会产生垃圾代码;程序员能够更清晰的控制运行过程,因此更安全、性能和架构等更清晰。
    入门“难”,深入“相对比较简单”

  4,什么是MVC模式
    模型(Model)、视图(View)、控制器(Controller)
    Model负责在View和控制器之间进行数据的传递(用户输入的内容封装成Model对象,发送给Controller);
    要显示的数据由Controller放到Model中,然后扔给View去显示。
    Controller不直接和View交互

  5,ASP.Net MVC与“三层架构”没有任何关系。
    唯一的“关系”:三层中的UI层可以用ASP.Net MVC来实现

  6,“约定大于配置”:

二、ASP.Net MVC起步

  1,项目的创建
    新建项目——C#——Web——ASP.NET Web应用程序(不要勾选“将Application Insights添加到项目”)——确定;
    选中“Empty”——勾选MVC(不要勾选Host in the cloud)——确定

  2,控制器的建立和视图的建立
    在Controller文件夹下右键——添加——控制器——选择“MVC5控制器-空”,
    注意:类的名字以Controller结尾,会自动在View文件夹下创建一个对应名字的文件夹(没有就手动创建文件夹)

    在View/文件夹名字 下创建视图Index(和XXXController的Index方法一致)
    注意:添加视图时,模板选择Empty,不要勾选创建为分部视图和使用布局页

  3,新建一个用来收集用户参数的类
    IndexReqModel(类名无所谓,可以随便起)包含Num1、Num2两个属性(只要不重名,大小写都可以)
    然后声明一个IndexRespModel类用来给view传递数据显示,有Num1、Num2、Result。
    也可以同一个类实现,但是这样写看起来比较清晰

    代码:

      public class TestControler:Controller
      {
        public ActionResult Index(IndexReqModel model)
        {
          IndexReqModel resq = new IndexReqModel();
          resq.num1 = model.Num1;
          resq.num2 = model.Num2;
          resq.result = model.Num1 + model.Num2;
          return View(resq);
        }
      }

 

  4,Index.cshtml的代码

    @model Test1.Models.IndexReqModel
    <!DOCTYPE html>

    <html>
      <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
      </head>
      <body>
        <div> 
          <input type="text" value="@Model.Num1" />+<input type="text" value="@Model.Num2" />[email protected]
        </div>
      </body>
    </html>

 

  5,在浏览器访问:http://localhost:56919/Test/Index?num1=1&num2=2

  6,执行过程、数据流动分析:
    当用户访问“Test/Index?num1=1&num2=2”的时候,会找到Controller下的TestController的Index方法去执行,
    把请求参数按照名字填充到Index方法的参数对象中(MVC引擎负责创建对象,给数据赋值,并且进行类型的转换),
    return View(resq)就会找到Views下的和自己的“类名、方法名”相对应的Index.cshtml,然后把数据resp给到Index.cshtml去显示。

    注意:
      1,@model Test1.Models.IndexReqModel //这里的model要小写开头,表示传递过来的数据是IndexReqModel类型的

      2,@Model指传递过来的对象 //这里的Model要大写开头

      3,cshtml模板就是简化HTML的拼接的模板,最终还是生成html给浏览器显示,不能直接访问cshtml文件

三、Razor语法

  1,语法简单:
    @启动的区域为标准的C#代码,其他部分是普通的html代码

  2,用法:

    @{string a = "abc";}    @a    @{C#代码块}    //有标签的就是html代码
    @Model    //控制器传递来的对象
    @Model.dog.Name    //控制器传递来的dog对象的Name属性的值
    @if(),@foreach()等C#语句

  3,在代码中输入大段文字
    两种方法:
      1,@:大段文字   //不推荐使用了,
      代码:

        if(Model.IsOK)
        {
          @:文字
        }

      2,<html标签>文字</html标签>
      代码:

        if(Model.IsOK)
        {
          <span>文字</span>
        }

    razor会智能识别哪块是C#,哪块是HTML,HTML中想运行C#代码就用@,想在C#中代码中输入HTML就写“HTML标签”。
    但是如果由于样式等原因不想加上额外的标签,那么可以用<text></text>标记,特殊的<text>不会输出到Html中。

  4,注意:不要在@item后写分号 //分号会被当成html代码,原样输出

  5,razor会自动识别哪块是普通字符,哪块是表达式,主要就是根据特殊符号来分辨(“识别到这里是否能被当成一个合法的C#语句”)。

    例子:
      不能这样写 <a href="[email protected]">,否则ashx会被识别为CourseId的一个属性,
      应该加上()强制让引擎把CourseId识别成一个单独的语法,<a href="Course(@CourseId).ashx">

    技巧:

      不确定的地方就加上(),也可以按照编辑器的代码着色来进行分辨

  6,如果不能自动提示,把页面关掉再打开就可以了。如果还是不能自动提示,只要运行没问题就行。
    cshtml文件中如果有警告甚至错误,只要运行没问题就没关系

  7,<span>[email protected]</span>,razor会自动识别出来是邮箱,所以razor不会把 @qq.com当成qq对象的com属性。
    但是对于特殊的邮箱或者就是要显示@,那么可以使用@转义@,也就是“@@”

      <li>[email protected]</span>//会把@item.Length识别成邮箱,

      因此用上()成为:

      <li>item_@(item.Length)</span>

  8,易错:
    要区分C#代码和html代码,

    正确的:style='display:(@message.IsHide?"none":"block")'

    错误的:style="display: (@message.IsHide) ? none : block"

    注意:
      为了避免C#中的字符串的“”和html的属性值的“”冲突,建议如果html属性中嵌入了C#代码,那么html的属性的值用单引号

  9,为了避免XSS攻击(跨站脚本攻击,在输出对象中嵌入script代码等恶意代码),Razor的@会自动把内容进行htmlencode输出,
    如果不想编码后输出,使用@Html.Raw()方法

  10,Razor的注释方法
    @*要注释的内容*@

  11,Razor中调用泛型方法的时候,由于<>会被认为是html转回标记模式,因此要用()括起来,比如@(Html.Test<string>)
    ()可以解决大部分问题,在View中一般不会调用复杂的方法

  12,如果cshtml中任何html标签的属性中以"~/"开头,则会自动进行虚拟路径的处理,
    当然一般是给<script>的src属性、<link>的href属性、<a>标签的href属性、<img>的src属性用的。

  13,html标签的任何属性的值如果是C#的值(使用@传递过来的值),
    如果是bool类型的值,那么如果值是false,则不会渲染这个属性,如果是true,则会渲染成“属性名=属性名”
    代码示例

    @{
      bool b1 = true;
      bool b2 = false;
    }
    <input type="checkbox" checked="@b1"/>//此时生成的html代码为:<input type="checkbox" checked="checked">

    这个特性避免了进行三元运算符的判断

  14,总结:
    1、@就是C#,<aaa></aaa>就是html

    2、如果想让被识别成html的当成C#那就用@()

    3、如果想让被识别成C#的当成html,用<span>等标签,如果不想生成额外的标签,就用<text></text>

    4、如果不想对内容htmlencode显示就用@Html.Raw()方法

    5、属性的值如果以"~/"开头会进行虚拟路径处理

    6、属性值如果是bool类型,如果是false就不输出这个属性,如果true就输出“属性名=属性名”<input type="checkbox" checked="@b1"/>

四、知识点补充和复习

  1,dynamic是C#语法中提供的一个语法,实现像JavaScript一样的动态语言,可以到运行的时候再去发现属性的值或者调用方法

    代码示例

    dynamic p = new dynamic();
    p.Name = "rupeng.com";
    p.Hello();

    注意:即使没有成员p.Age=3;编译也不会报错,只有运行的时候才会报错
      好处是灵活,坏处是不容易在开发的时候发现错误、并且性能低

    如果dynamic指向System.Dynamic.ExpandoObject()对象,这样可以给对象动态赋值属性(不能指向方法):

    dynamic p = new System.Dynamic.ExpandoObject();
    p.Name = "rupeng.com";
    p.Age = 10;
    Console.WriteLine(p.Name+","+p.Age);

  2,var类型推断

    var i = 3;
    var s ="abc";

    编译器会根据右边的类型推断出var是什么类型

    var和dynamic的区别:
      var是编译的时候确定的,dynamic是在运行的时候动态确定的
      var变量不能指向其他类型,dynamic可以(因为var在编译的时候已经确定了类型)

  3,匿名类型

    匿名类型是C#中提供的一个新语法:
    var p = new {Age=5,Name="rupeng.com"};//这样就创建了一个匿名类的对象,这个类没有名字,所以叫匿名类
    原理:
      编译器生成了这个类,这个类是internal、属性是只读的、初始值是通过构造函数传递的
    因此:
      因为匿名类的属性是只读的,所以匿名类型的属性是无法赋值的;
      因为匿名类型是internal,所以无法跨程序集访问其成员(只能活在自己当前的程序集内)。

五、Controller给View传递数据的方式

  1,ViewData:
    以ViewData["name"]="rupeng";string s =(string)ViewData["name"]这样的键值对的方式进行数据传送

  2,ViewBag:
    ViewBag是dynamic类型的参数,是对ViewData一个动态类型封装,用起来更方便,和ViewData共同操作一个数据。ViewBag.name="";
    @ViewBag.name。
 

   用ViewBag传递数据非常方便,但是因为ASP.Net MVC中的“Html辅助类”等对于ViewBag有一些特殊约定,一不小心就跳坑了(http://www.cnblogs.com/rupeng/p/5138575.html),所以尽量不要用ViewBag,而是使用Model。

  3、Model:
    可以在Controller中通过return View(model)赋值,然后在cshtml中通过Model属性来访问这个对象;

    如果在cshtml中通过“@model 类型”(注意model小写)指定类型,则cshtml中的Model就是指定的强类型的,这样的cshtml叫“强类型视图”;

    如果没有指定“@model 类型”, 则cshtml中的Model就是dynamic。

六、关于Action的参数
  ASP.Net MVC5会自动对参数做类型转换

  对于boolean类型的参数(或者Model的属性),如果使用checkbox,则value必须是“true”,否则值永远是false。对于double、int等类型会自动进行类型转换

  1,一个Controller可以有多个方法,这些方法叫Action。通过“Controller名字/方法名”访问的时候就会执行对应的方法。

  2,Action的三种类型的参数:
    普通参数、Model类、FormCollection

    1,普通参数:
      Index(string name,int age)。框架会自动把用户Get请求的QueryString或者Post表单中的值根据参数名字映射对应参数的值,
      适用于查询参数比较少的情况。

      注意:int类型的可空问题

    2,Model类。叫ViewModel。

    3,FormCollection,采用fc["name"]这种方法访问,类似于HttpHandler中用context["name"]。

      适用于表单元素不确定、动态的情况

  3,Action的方法不能重载,所以一个Controller中不能存在两个同名的Action

    错误代码:
      public ActionResult T1(string name)和public ActionResult T1(int Age)不能同时存在

    特殊情况:
      给Action方法上标注[HttpGet]、[HttpPost],注意当发出Get或者Post请求的时候就会执行相应标注的方法,变相实现了同名的Action

    常见的应用方法:
      把需要展示的初始页面的Action标注为[HttpGet],把表单提交的标注为[HttpPost]

  4,Action参数可以一部分是普通参数,一部分为Model
    代码示例:

      public ActionResult T1(string name,Classes className)

  5,Action参数如果在请求中没有对应的值,就会去默认值:
    Model类的形式则取默认值:int是0、boolean是false、引用类型是null。
    普通参数的形式:取默认值会报错,如果允许为空,要使用int?,也可以使用C#的可选参数语法来设定默认值
    示例代码:

      Index(string name="tom");

  6,上传文件的参数用HttpPostedFileBase类型,


七、View的查找
  1,return View()会查找Views的Controller名字的Action的名字的cshtml

  2,return View("Action1"),查找Views的Controller名字下的“Action1.cshtml”,如果找不到则到特殊的shared文件夹下找“Action1.cshtml”

  3、return View("Action1")中如何传递model?return View("Action1",model)。
    陷阱:如果model传递的是string类型,则需要return View("Action1",(object)str)为什么?看一下重载!

    注意:
      return View("Action1")不是重定向,浏览器和服务器之间只发生了一次交互,地址栏还是旧的Action的地址。
      这和重定向return Redirct("/Index/Action1");不一样
    应用:

      执行报错,return View("Error",(object)msg) 通用的报错页面。为了防止忘了控制重载,封装成一个通用方法。

八、其他类型的ActionResult

  1,View()是一个方法,它的返回值是ViewResult类型,ViewResult继承自ActionResult,
    如果在确认返回的是View(),返回值写成ViewResult也行,但是一般没这个必要,因为那样就不灵活了。因为ViewResult还有其他子类

  2,RedirectResult,重定向,最终就是调用response.Redirect()。
    用法:

      return Redirect("http://www.rupeng.com");//重定向到rupeng
      return Redirect("~/1.html");//重定向到

  3,ContentResult
    返回程序中直接拼接生成的文本内容

    return Content(string content,string contentType)

  4,文件 return File();

  1return File(byte[] fileContents,string contentType);//返回byte[]格式的数据
  2return File(byte[] fileContents,string contentType,fileDownLoadName);//fileDownLoadName:设定浏览器端弹出的建议保存的文件名
  3return File(Stream fileStream, string contentType) 返回Stream类型的数据(框架会帮着Dispose,不用也不能Dispose)
  4,FileStreamResult
    return File(Stream fileStream,string contentType,string fileDownLoadName)
  5, File(string fileName, string contentType)// 返回文件名指定的文件,内部还是流方式读取文件;
  6, File(string fileName, string contentType, string fileDownloadName)
  //如果是返回动态生成的图片(比如验证码),则不用设置fileDownloadName;如果是“导出学生名单”、“下载文档”等操作则要设定fileDownloadName。

  注意:如果在Controller中要使用System.IO下的File类,因为和File方法重名了,所以要用命名空间来引用了。

  5,return HttpNotFound();

  6,return JavaScript(string script);
    返回JavaScript代码字符串,和return Content("alert('Hello World');","application/x-javascript");效果一样。
    因为违反三层原则,尽量不要使用

  7,Json
    JsonResult Json(object data) 把data对象序列化为json字符串返回客户端,并且设置contentType为"application/json"

    Json方法默认是禁止Get请求的(主要为了防止CSRF攻击,举例:在A网站中嵌入一个请求银行网站给其他账号转账的Url的img),只能Post请求。所以如果以Get方式访问是会报错的。

    如果确实需要以Get方式方式,需要调用return Json(data, JsonRequestBehavior.AllowGet)

    ASP.NET MVC 默认的Json方法实现有如下的缺点:
      1,日期类型的属性格式化成字符串是“\/Date(1487305054403)\/"这样的格式,在客户端要用js代码格式化处理,很麻烦。

      2,json字符串中属性的名字和C#中的大小写一样,不符合js中“小写开头、驼峰命名”的习惯。在js中也要用大写去处理。

      3,无法处理循环引用的问题(尽管应该避免循环引用),会报错“序列化类型为***的对象时检测到循环引用”
  8,重定向

    1,Redirect(string url)
    2,RedirectToAction(string actionName,string controllerName);//其实就是帮助拼接生成url,最终还是调用Redirect(),

    3,两者的区别:
      RedirectToAction是让客户端重定向,是一个新的Http请求,所以无法读取ViewBag中的内容;
      return View()是一次服务器一次处理转移

      Redirect和return View 的区别:

        1、 Redirect是让浏览器重定向到新的地址;return View是让服务器把指定的cshtml的内容运行渲染后给到浏览器;

        2、 Redirect浏览器和服务器之间发生了两次交互;return View浏览器和服务器之间发生了1次交互

        3、 Redirect由于是两次请求,所以第一次设置的ViewBag等这些信息,在第二次是取不到;而View则是在同一个请求中,所以ViewBag信息可以取到。

        4、 如果用Redirect,则由于是新的对Controller/Action的请求,所以对应的Action会被执行到。如果用View,则是直接拿某个View去显示,对应的Action是不执行的。

      什么情况用View?服务器端产生数据,想让一个View去显示的;
      什么情况用Redirect?让浏览器去访问另外一个页面的时候。

九、杂项Misc
  1、TempData
    在SendRedirect客户端重定向或者验证码等场景下,由于要跨请求的存取数据,是不能放到ViewBag、Model等中,

    需要“暂时存到Session中,用完了删除”的需求:实现起来也比较简单:

    存入:
      Session["verifyCode"] = new Random().Next().ToString();
    读取:
    String code = (string) Session["verifyCode"];
    Session["verifyCode"] = null;
    if(code==model.Code)
    {
      //...
    }

    ASP.Net MVC中提供了一个TempData让这一切更简单。
    在一个Action存入TempData,在后续的Action一旦被读取一次,数据自动销毁。
    TempData默认就是依赖于Session实现的,所以Session过期以后,即使没有读取也会销毁。

    应用场景:验证码;

  2、HttpContext与HttpContextBase、HttpRequest与HttpRequestBase、HttpPostedFile与HttpPostedFileBase。

    注意:进行asp.net mvc开发的时候尽量使用****Base这些类,不要用asp.net内核原生的类。HttpContext.Current(X)

      1)在Controller中HttpContext是一个HttpContextBase类型的属性(真正是HttpContextWrapper类型,是对System.Web.HttpContext的封装),System.Web.HttpContext是一个类型。这两个类之间没有继承关系。
        System.Web.HttpContext类型是原始ASP.Net核心中的类,在ASP.Net MVC中不推荐使用这个类(也可以用)。

      2)HttpContextBase能“单元测试”,System.Web.HttpContext不能。

      3)怎么样HttpContextBase.Current?其实是不推荐用Current,而是随用随传递。

      4)HttpContextBase的Request、Response属性都是HttpRequestBase、HttpResponseBase类型。Session等也如此。

      5)如果真要使用HttpContext类的话,就要System.Web.HttpContext

  3,Views的web.config中的system.web.webpages.razor的pages/namespaces节点下配置add命名空间,这样cshtml中就不用using了

    示例代码:

      <system.web.webPages.razor>
        <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <pages pageBaseType="System.Web.Mvc.WebViewPage">
          <namespaces>
            <add namespace="System.Web.Mvc" />
            <add namespace="System.Web.Mvc.Ajax" />
            <add namespace="System.Web.Mvc.Html" />
            <add namespace="System.Web.Routing" />
            <add namespace="Test1" />
          </namespaces>
        </pages>
      </system.web.webPages.razor>

  4,Layout布局文件
    @RenderBody()渲染正文部分;cshtml的Layout属性设定Layout页面地址;
    @RenderSection("Footer")用于渲染具体页面中用@section Footer{}包裹的内容,如果Footer是可选的,那么使用@RenderSection("Footer",false),
      可以用IsSectionDefined("Footer")实现“如果没定义则显示***”的效果。
  
  5, 可以在Views文件夹下建一个_ViewStart.cshtml文件,在这个文件中定义Layout,这样不用每个页面中都设定Layout,
    当然具体页面也可以通过设定Layout属性来覆盖默认的实现;

  6,@Html.DropDownList
    如果在页面中输出一个下拉列表或者列表框,就要自己写foreach拼接html,还要写if判断哪项应该处于选中状态

    <select>
      @foreach(var p in (IEnumerable<Person>)ViewBag.list)
      {
        <option selected="@(p.Id==3)">@p.Name</option>
      }
    </select>

    asp.net mvc中提供了一些“Html辅助方法”(其实就是Controller的Html属性中的若干方法,其实是扩展方法)用来简化html代码的生成。

    DropDownList是生成下拉列表的。
      1)DropDownList(this HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList)
        string name参数用来设定 <select>标签的name属性的值,id属性的值默认和name一致。
        下拉列表中的项(<option>)以SelectListItem集合的形式提供,SelectListItem的属性:
        bool Selected:是否选中状态,也就是是否生成selected="selected"属性;
        string Text:显示的值,也就是<option>的innerText部分;
        string Value:生成的value属性,注意是string类型;

        示例代码:

          List<Person> list = new List<Person>();
          list.Add(new Person { Id=1,Name="lily",IsMale=false});
          list.Add(new Person { Id = 12, Name = "tom", IsMale = true });
          list.Add(new Person { Id = 13, Name = "lucy", IsMale = false });


          List<SelectListItem> sliList = new List<SelectListItem>();
          foreach (var p in list)
          {
            SelectListItem listItem = new SelectListItem();
            listItem.Selected = (p.Id==2);
            listItem.Text = p.Name;
            listItem.Value = p.Id.ToString();
            sliList.Add(listItem);
          }
          return View(sliList);
        @model IEnumerable<SelectListItem>
        <!DOCTYPE html>

        <html>
          <head>
            <meta name="viewport" content="width=device-width" />
            <title>DDL</title>
          </head>
          <body>
            <div> 
              @Html.DropDownList("pid", Model);
            </div>
          </body>
        </html>

    2)DropDownList(this HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, object htmlAttributes)
      htmlAttributes属性用来生成select标签的其他属性,通常以匿名类对象的形式提供,
      比如new { onchange = "javascript:alert('ok')", style = "color:red", aaa = "rupeng", id = "yzk",@class="warn error" }
      生成的html源码为:

      <select aaa="rupeng" class="warn error" id="yzk" name="pid" onchange="javascript:alert(&#39;ok&#39;)" style="color:red">

      支持自定义属性,给你原样输出,具体什么含义自己定;
      由于class是关键字,所以不能直接用class="",要加上一个@前缀,这其实是C#中给变量名取名为关键字的一种语法;
      注意:
        id默认和name一致,如果设定了id则覆盖默认的实现。

    3)构造一个特殊的集合类SelectList,他会自动帮着做集合的遍历

      public ActionResult DDL2()
      {
        List<Person> list = new List<Person>();
        list.Add(new Person { Id=666,Name="zhangsan",IsMale=false});
        list.Add(new Person { Id = 222, Name = "tom", IsMale = true });
        list.Add(new Person { Id = 333, Name = "lucy", IsMale = false });

        SelectList selectList = new SelectList(list, "Id", "Name");
        return View(selectList);
      }
      @Html.DropDownList("name",(SelectList)Model);

      IEnumerable items参数用来显示的原始对象数据,string dataValueField为“对象的哪个属性用做生成value属性”,
      string dataTextField为“对象的哪个属性用作生成显示的文本属性”。

      用SelectList的好处是简单,但是如果说要同时显示多个属性的时候,就只能用非SelectList的方式了。

      SelectList还可以设定第四个参数:
        哪个值被选中:SelectList selectList = new SelectList(list,"Id","Name",222);

      一个坑:不能让cshtml中的DropDownList的第一个name参数和ViewBag中任何一个属性重名http://www.cnblogs.com/rupeng/p/5138575.html。
      建议不要通过ViewBag传递,都通过Model传递

  7,@Html.ListBox()
      和@Html.DropDownList()类似

  8,为什么不再推荐使用“Html辅助方法”

    坏处:因为不符合复杂项目的开发流程(前端程序员可能看不懂),

    好处:可以把表单验证、绑定等充分利用起来,开效率高,
      但是在互联网项目中开发效率并不是唯一关注因素。在asp.net mvc6中已经不再推荐使用html辅助方法的表单了

  9,Request.IsAjaxRequest()
    判断是来自于Ajax请求,这样可以让ajax请求和非ajax请求响应不同的内容
    原理:
      Ajax请求的报文头中有x-requested-with: XMLHttpRequest。
      如果使用System.Web.HttpContext,那么是没有这个方法的,那么自己就从报文头中取数据判断。

    示例代码:

      public ActionResult Ajax1()
      {
        return View();
      }
      public ActionResult Ajax2()
      {
        Person p = new Person();
        p.Name = "rupeng";
        if (Request.IsAjaxRequest())
        {
          return Json(p);
        }
        else
        {
          return Content(p.Name);
        }
      }

  10,数据验证
    1,asp.net mvc会自动根据属性的类型进行基本的校验,比如如果属性是int类型的,那么在提交非整数类型的数据的时候就会报错。
      注意ASP.net MVC并不是在请求验证失败的时候抛异常,而是把决定权交给程序员,程序员需要决定如何处理数据校验失败。

      在Action中根据ModelState.IsValid判断是否验证通过,如果没有通过下面的方法拿到报错信息
      示例代码:

      public ActionResult Index(IndexModel model)
      {
        if (ModelState.IsValid)
        {
          return Content("Age=" + model.Age);
        }
        else
        {
          return Content("验证失败");
        }
      }

      在参数很多的情况下使用下面的封装的方法:

      public static string GetValidMsg(ModelStateDictionary modelState)
      {
        StringBuilder sb = new StringBuilder();
        foreach (var propName in modelState.Keys)
        {
          if (modelState[propName].Errors.Count <= 0)
          {
            continue;
          }
          sb.Append("属性【").Append(propName).Append("】错误:");
          foreach (var modelError in modelState[propName].Errors)
          {
            sb.AppendLine(modelError.ErrorMessage);
          }
        }
        return sb.ToString();
      }

 

    2,ASP.Net MVC提供了在服务器端验证请求数据的能力。要把对应的Attribute标记到Model的属性上(标记到方法参数上很多地方不起作用)。

      常用验证Attribute:
        a) [Required]   这个属性是必须的

        b) [StringLength(100)],  字符串最大长度100;[StringLength(100,MinimumLength=10)]长度要介于10到100之间

        c) [RegularExpression(@"aa(\d)+bb")]   正则表达式

        d) [Range(35,88)]  数值范围。字符串长度范围的话请使用[StringLength(100,MinimumLength=10)]

        e) [Compare("Email")]  这个属性必须和Email属性值一样。

        f) [EmailAddress]   要是邮箱地址

        g) [Phone]  电话号码,规则有限

      示例代码:

      public class IndexModel
      {
        [Required]
        public int Age { get; set; }
        public long Id { get; set; }
        public string Name { get; set; }
        [StringLength(11)]
        public string PhoneNum { get; set; }
      }

    3, 验证Attribute上都有ErrorMessage属性,用来自定义报错信息。ErrorMessage中可以用{0}占位符作为属性名的占位。
      示例代码:

      [Required(ErrorMessage="不能为空")]
      public int Age { get; set; }    

    4, 数据验证+Html辅助类高级控件可以实现很多简化的开发,连客户端+服务器端校验都自动实现了,但是有点太“WebForm”了,因此这里先学习核心原理,避免晕菜。

  11,自定义验证规则ValidationAttribute,
    自动的验证规则需要直接或者间接继承自ValidationAttribute

    1,使用正则表达式的校验,直接从RegularExpressionAttribute继承

      示例代码:
        public class QQNumberAttribute : RegularExpressionAttribute
        {
          public QQNumberAttribute() : base(@"^\d{5,10}$")//不要忘了^$
          {
            this.ErrorMessage = "{0}属性不是合法的QQ号,QQ号需要5-10位数字";
            //设定ErrorMessage的默认值。使用的人也可以覆盖这个值
          }
        }

      手机号的正则表达式:@"^1(3[0-9]|4[57]|5[0-35-9]|7[01678]|8[0-9])\d{8}$"


    2,直接继承自ValidationAttribute,重写IsValid方法

      比如校验中国电话号码合法性

      public class CNPhoneNumAttribute : ValidationAttribute
      {
        public CNPhoneNumAttribute()
        {
          this.ErrorMessage = "电话号码必须是固话或者手机,固话要是3-4位区号开头,手机必须以13、15、18、17开头";
        }
        public override bool IsValid(object value)
        {
          if (value is string)
          {
            string s = (string)value;
            if (s.Length == 13)//手机号
            {
              if (s.StartsWith("13") || s.Sta 

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
ASP.NET(C#)图片加文字、图片水印,神啊,看看吧发布时间:2022-07-10
下一篇:
ASP.Net定时任务执行发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap