【MVC】知识笔记

  MVC代表:模型-视图-控制器。

Models:标识该应用程序的数据并使用验证逻辑来强制实施业务规则的数据类

Views  :应用程序动态生成HTML所使用的模版文件

Controllers:处理浏览器的请求,取得数据模型,然后指定要响应浏览器请求的视图模版

Mvc框架:浏览器请求服务器的某个控制器类的Action方法,方法中可以调用业务层等代码处理业务,并产生数据Model,交给视图引擎,视图引擎会找到对应视图,并将数据 “填充到“视图上对应的位置,最终产生整个页面的Html代码,返回给浏览器

MVC与WebForm的区别

1. webform

优点:有大量的webform控件,开发速度快

 缺点:页面开发与后台混合在一起;容易出现大量的viewstate,对后台压力比较大

2. MVC

优点:

  • 层次节点清晰,开发分工更好
  • URL 更有意义, 有路由机制
  • 可以复用视图
  • 性能优于WebForm,比较适合大型项目,开发成本较高,但耦合度低,易于维护,

缺点:没有太多的现成控件,开发效率较低。

更多参考:MVC与WebForm的区别

一、@Styles.Render() @Scripts.Render()打包压缩 

好处:一次性加载css、js文件,提高性能

就是可以把多个css文件在一起请求,浏览器只发一次请求  不过必须在Global.asax里面 加一段代码  BundleTable.EnableOptimizations = true;

而且 当页面下次再次发送请求的时候 BundleConfig里面没有更改的话 浏览器会从缓存中去取 ,这一点大大提高了性能 ...

参考:Mvc4_@Styles.Render提高性能

 ASP.NET MVC 4 RC的JS/CSS打包压缩功能 Scripts.Render和Styles.Render

 实践:

1、添加一系列css和js文件(bootstrap、jQuery),

2、在cshtml文件中添加大量的css,f12看 network请求量和时间。

3、改造:在App_Start->BundleConfig.cs中,把要添加的css文件include进来【需要添加引用using System.Web.Optimization;】

4、Global.asax中增加 BundleConfig.RegisterBundles(BundleTable.Bundles);

6、@Styles.Render("~/Content/css")  ,运行,f12查看。【js同理.@Scripts.Render("~/bundles/jquery");】

7、注意的是,webconfig中的设置: <compilation debug="false" targetFramework="4.5" />,这里一定要设置为false,如果设置为true,在预览页面的时候,不会压缩这些文件,

问题:mvc中的 @Styles @Scripts 上下文找不到  是因为缺少引用System.Web.Optimization.dll,Viewsweb.config中也需要加【注意是Views中的配置文件】,在cshtml中加@using System.Web.Optimization也是可以的

二、Form表单提交 

1.cshtml页面form提交

<div>
    @using (Html.BeginForm("AddNews", "Form", FormMethod.Post))
    {
        <input name="text1" type="text" />
        <input name="text2" type="text" />
        <input class="btn btn-success" type="submit" value="提交" />
    }
</div>

<div>
    @using (Html.BeginForm("AddNews2", "Form", FormMethod.Post))
    {
        <input name="text1" type="text" />
        <input name="text2" type="text" />
        <input class="btn btn-success" type="submit" value="提交" />
    }
</div>

<div>
    @using (Html.BeginForm("AddNews3", "Form", FormMethod.Post))
    {
        <input name="text1" type="text" />
        <input name="text2" type="text" />
        <input class="btn btn-success" type="submit" value="提交" />
    }
</div>

<div>
    @using (Html.BeginForm("AddNews4", "Form", FormMethod.Post))
    {
        <input name="text1" type="text" />
        <input name="text2" type="text" />
        <input class="btn btn-success" type="submit" value="提交" />
    }
</div>
View Code

2.控制器处理表单提交数据4种方式

#region 控制器处理表单提交数据4种方式

        /// <summary>
        /// 方法1:使用传统的Request请求取值
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public ActionResult AddNews()
        {
            string a = Request["text1"];
            string b = Request["text2"];
            return Json(a + b, JsonRequestBehavior.AllowGet);  //在页面上显示"a+b"
        }

        /// <summary>
        ///  方法2:Action参数名与表单元素name值一一对应
        /// </summary>
        /// <param name="text1"></param>
        /// <param name="text2"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult AddNews2(string text1, string text2)
        {
            string a = text1;
            string b = text2;
            return Json(a + b, JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// 方法3:从MVC封装的FormCollection容器中读取
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult AddNews3(FormCollection form)
        {
            string a = form["text1"];
            string b = form["text2"];
            return Json(a + b, JsonRequestBehavior.AllowGet);

        }


        /// <summary>
        /// 方法4:使用实体作为Action参数传入,前提是提交的表单元素名称(name)与实体属性【注意不能是 字段】名称一一对应
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult AddNews4(UserModel user)
        {
            string a = user.text1;
            string b = user.text2;
            return Json(a + b, JsonRequestBehavior.AllowGet);
        }


        #endregion
View Code

注意:使用实体作为Action参数传入,前提是提交的表单元素名称(name)与实体属性【注意不能是 字段】名称一一对应,不区分大小写。

3.一个表单,两个提交按钮实现不同地址/Action提交

有时项目中有需要将同一个表单提交到不同的两个路由地址。
此时就可以用到下面的方法:
1.form自带属性:

@using (Html.BeginForm("List", "ExpertBooking", FormMethod.Post, new { id = "frmReport" }))
{
<input data-action="@Url.Action("List")" type="submit" value=" 查詢 " id="btnSearch" class="el-submit" />
<input type="submit" value=" 導出Excel " id="btnExport" formaction="ExportOrderList" class="el-submit" />
}

在默认的提交路由是BeginForm中定义的,在下面formaction里面填写另一个需要提交的Action。 提交地址可以写成 formaction="{:url('****')}"

2.点击事件:
可以将两个提交的submit不使用input标签,改成button标签, 在标签中设置onclick单击事件,在js中去处理提交。

更多参考:ASP.NET MVC中实现多个按钮提交的几种方法

三、Mvc.Controller. RedirectToAction() 

该方法将HTTP 302响应返回到浏览器并会导致浏览器对指定的操作发出 GET 请求。该方法重载列表如下:

名称 说明

RedirectToAction(String)           使用操作名称重定向到指定的操作。

RedirectToAction(String, Object)   使用操作名称和路由值重定向到指定的操作。

RedirectToAction(String, String)   使用操作名称和控制器名称重定向到指定的操作。

RedirectToAction(String, RouteValueDictionary)使用操作名称和路由字典重定向到指定的操作

RedirectToAction(String, String, Object)   使用操作名称、控制器名称和路由值重定向到指定的操作

RedirectToAction(String, String, RouteValueDictionary)   使用操作名称、控制器名称和路由字典重定向到指定的操作

  •  在Action间跳转 RedirectToAction 传值参数问题

return RedirectToAction("Test", new { cw = cw, firstdirectoryid = firstdirectoryid });

上式中cw是一个对象,按上式传递参数后,在Test中收不到对象cw,但值类型的firstdirectoryid可以接收到。

RedirectToAction函数允许传递一系列的objects,但在实践中发现,这些所谓的objects,并不是真正的objects,调用者 若传递出object reference,接收者得到的都是null。

其实,RedirectToAction转移使用的是HTTP协议,只有值变量才能被传递如果需要传递 objects,可以使用TempData和Session

  在ASP.NET MVC框架的ControllerBase中存在一个叫做TempData的Property。它的类型为TempDataDictionary,顾名思义是一个字典类。

TempData在ASP.NET MVC中的作用是:可用于在Action执行过程之间传值。简单的说,可以在执行某个Action的时候,将数据存放在TempData中。

那么在下一次Action执行过程中可以使用TempData中的数据。

如:

 public ActionResult Index()
 {
 this.TempData["MyNane"] = "XiaoMing";
 return View();
 }
public ActionResult Index2()
 {
 string MyName=this.TempData["MyNane"] as string;
 return View();
}
View Code

所以在Action之间跳转时需要传递值类型的,使用变量就可以,引用类型请使用TempData来传递

四、View中model的大小写问题

@model 是用来定义此页面的强类型,这个是 Razor 视图引擎定义强类型的语法, 而 Model 则是每个页面 强类型的声明变量, 所谓强类型视图,就是通过@model指令 指明当前Model(属性)的具体类型。
@model是给编译器看的,让它知道Model的具体类型。

Eg:这个@model IEnumerable<MVCTest.Models.MovieDB>正是来告诉视图,这个视图的model属性到底是个什么属性,然后便可以通过控制器传过来的模型分别填充下面的强类型空缺

五、@Url.Action 前端跳转链接

Url.Action()方法在asp.net mvc中也是比较常用的方法,其有8种重载方法,每一种重载方法的用法见下表。

常用:Action(String, String, Object)

使用指定的操作名称、控制器名称和路由值生成操作方法的完全限定 URL

@Url.Action("action1", "controller1", new { id=1, orderID = Model.OrderID, isModify = true })

使用:

<a onclick="window.open('@Url.Action("ModifyOrder", "ExpertsBooking", new { orderID = Model.OrderID, isModify = true })')" href="javascript:void(0);" > 修改訂單<br /></a>

六、@Html.ActionLink()的使用详解

   微软采用一种全新的方式来表示从前的超链接方式,它代替了从前的繁杂的超链接标签,让代码看起来更加简洁。通过浏览器依然会解析成传统的a标签。除此之外,还允许我们添加Html属性。

@Html.ActionLink("linkText", "actionName", "controllerName", routeValues, htmlAttributes)

第一个参数:该链接要显示的文字

第二个参数:对应的控制器的方法(Action),默认控制器为当前页面对应的控制器

第三个参数:指定控制器的名称

第四个参数:routeValue可以向action传递参数。new { id = "1", Director ="林峰"}

第五个参数:可以设置<a>标签的属性

   假如生成<a href="Products/Detail/1?Director=%E6%9E%97%E5%B3%B0'

在Controller中使用string director = Request.QueryString["Director"];来获取。

例如,

1、@Html.ActionLink("detail", "Detail",”Products” new{ id = 1 }, new{ target = "_blank" })

会生成<a href="Products/Detail/1" target="_blank">detail</a>

需要注意的是如果写成new{ target="_blank", class="className" }则会报错,因为Class是C#的关键字,此时应该写成@class="className"

 2、$("#partialDiv").load('/Ajax/ListPage/1?Director=%E6%9E%97%E5%B3%B0&amp;hello=tansha')

传递超过两个参数时:new { id = "1", hello="tansha",Director = "林峰"})

$("#partialDiv").load('/Ajax/ListPage/1?hello=tansha&amp;Director=%E6%9E%97%E5%B3%B0')

注:"&amp;"就是'&' 只是在HTML中的&用&amp;来表示

七、@html. DropDownList

控制器中:

var parkings = db.GV_INFO_PARKING.Where(d => d.STATUS == 1).Select(s => new SelectListItem()
            {
                Text = s.NAME,
                Value = s.ID
            });
            ViewData["parkings"] = parkings;

视图中

 若  @Html.DropDownList("parkings",ViewData["parkings"] as IEnumerable<SelectListItem>,"全部", new { @class = "form-control" })

则生成的源代码  <select class="form-control" id="parkings" name="parkings">

<option value="">全部</option>

若 @Html.DropDownList("车场",ViewData["parkings"] as IEnumerable<SelectListItem>,"全部", new { @class = "form-control" })

则生成的源代码  <select class="form-control" name="车场">

<option value="">全部</option>

八、@Html.Partial和@Html.Action区别

  • 首先看一下它们的对等关系

@Html.Partial 对应 @{Html.RenderPartial();}
@Html.Action 对应 @{Html.RenderAction();}

以上相互对应的语句,它们实现的功能是一样的,不同的就是写法。

  • 原理

Action加载方法的视图,执行 Controller → Model → View 的顺序,然后把产生的页面带回到原来的View中再回传。

而Partial直接加载视图文件内容

  • 区别

@Html.Partial可以直接提供用户控件名作为参数,而@Html.Action需要有对应的Action,在Action内部返回PartailResult(retun PartialView())

Eg:

@Html.Action("InsuranceList", new { startDate = startDate.Date, endDate = endDate.Date, tmpOrderID = tmpOrderID })

如:下面例子可以说明@Html.Partial的用法

public ActionResult Index()
{
    string[] txtArry = { "1", "2", "3" };
    ViewData["txt"] = "欢迎";
    return View(txtArry);
}

index.cshtml页面

<body>

    <div>

        @*这里应该显示:1*@

        @Model[0]

    </div>

    <div>

        @*调用msg1.cshtml*@

        @Html.Partial("msg1")

    </div>

</body>
View Code

如果@Html.Partial("msg1")没有传具体的值,那么它就会默认把index里的Model值传过去,如果有具体的参数,那么msg1里的Model值就是为传过来的参数值

如:@Html.Partial("msg1",(object)Model[1])

msg1.cshtml页面

<body>

    <div>

        @Model[0]+@ViewData["txt"]

    </div>

</body>
View Code

总结:用@Html.Partial(页面),那么这个页面的里的数据源是“调用页面:index.cshtml”给的,只要index页面可以接受到的viewdata那么msg1就可以接受,index页面就是msg1页面的衣食父母。最后根据不同的用途来选择吧

九、@EditorFor  @TextBoxFor @TextBox

  •  Html.EditorFor与Html.TextBoxFor

EditorFor 是映射到Model 属性上面,忽略用户自定义属性和样式 ,Model 可以为null
TextBoxFor是映射到Model 属性上面,可以用户自定义属性和样式,Model 不可以为null

使用Html.EditorFor()为文本框加上maxlength,placeholder等属性,比较麻烦,可以使用Html.TextBoxFor()直接加属性

Eg:@Html.TextBoxFor(p => p.XingEN, new { maxlength = "28" })

用法:<td colspan="3">@Html.EditorFor(p => p.FareAirline, "AirlineSelector")</td>

  •  Html.TextBox与Html.TextBoxFor

最终它们都生成相同的HTML,但Html.TextBoxFor()是强类型的,而Html.TextBox则不是。

@Html.TextBox("Price")

@Html.TextBoxFor(m=> m.ToList().First().Price)

生成的html源代码,TextBoxFor会绑定模型的数据。

<input id="Price" name="Price" type="text" value="">

<input id="Price" name="Price" type="text" value="52">

@Html.TextBoxFor 可以直接绑定model,其实是让你的View跟Model同步起来。当你改动Model的时候,不用手动去修改html tag。

十、@RenderBody() @RenderPage("") @RenderSection("")

  模板页:@RenderBody()占位符;当创建基于_Layout.cshtml布局页面的视图时,视图的内容会和布局页面合并,

  局部页面:@RenderPage("");呈现一个页面。比如网页中固定的头部可以单独放在一个共享的视图文件中,然后在布局页面中通过这个方法调用。

  模板页预设区域:@RenderSection("");布局页面还有节(Section)的概念,也就是说,如果某个视图模板中定义了一个节,那么可以把它单独呈现出来

为了防止因缺少节而出现异常,可以给RenderSection()提供第2个参数:@RenderSection("head", false)或

@if (IsSectionDefined("head")){@RenderSection("head", false)}

else{<p>SubMenu Section is not defined!</p>}

例子:

<!DOCTYPE html>

<html>

<head>

    <title>@ViewBag.Title</title>

    <link href="@Url.Content("~/Content/Site。css")" rel="stylesheet" type="text/css" />

    <script src="@Url.Content("~/Scripts/jquery-1.4.4.min。js")" type="text/javascript"></script>

    @RenderSection("head", required: true)@*View页面自定义特定js/css使用*@

</head>

<body>

    @RenderPage("~/Views/Shared/_Header。cshtml")

    @RenderBody()

</body>

</html>
View Code

十一、动态改变样式

当订单为某些状态时,某些链接不可单击且置灰

方法一(推荐)

var orderCurrentStatus = Model.OrderStatus;
var cancelStatus = (byte)ExpertOrderStatus.AlreadyCancel;
var cssAdd = "pointer-events:none;color:gray"; //置灰且不可单击

 <a href="Index?orderID=@Model.OrderID" style="@(orderCurrentStatus==cancelStatus?cssAdd:"")">編輯訂單詳情</a>
View Code

方法二:

var orderCurrentStatus = Model.OrderStatus;
var cancelStatus = (byte)ExpertOrderStatus.AlreadyCancel;
var cssAdd = "pointer-events:none;color:gray"; //置灰且不可单击

@{ if (orderCurrentStatus == cancelStatus)
{
<a href="#" onclick="CancelOrder()" style="pointer-events:none;color:gray">取消訂單</a>
}
else
{
<a href="#" onclick="CancelOrder()">取消訂單</a>
}
}
View Code

十二、控制器方法中返回跳转

  当控制器方法中处理完请求,

想跳转某个地址时,eg:return Redirect("https://www.baidu.com/");

想跳转到某个view页面。eg: return RedirectToAction("Detail", new { orderID = orderID });

新开页面跳转,一般会想到前端 <a> target=_blank,或者前端js请求后端时采用:window.open("CreatePoly?orderID=" + orderid);

  不开新页面的方式:window.location.href = "CreateInput?orderID=" + orderid;

原文地址:https://www.cnblogs.com/peterYong/p/10639597.html