MVC笔记 MVC注意事项及优化

2023-05-16

一、 学习MVC注意事项

1. 了解不同的项目类型

      从ASP.NET 2.0开始,vs针对网站开发区分了两种项目类型,一种是'项目'(Website Project),另一种是'网址'(Web Application Project)。两者最大的差别在于'项目'采用动态编译的架构运作。如:中只要编辑并存储了'App_Code'目录下的类或强类型数据集,就会使整个网站项目在后台重新编译,有时甚至会阻碍在vs中进行操作,若项目规模变大,就很容易拖慢开发速度。而MVC要求项目类型最好是'网址',可以利用自动化辅助功能开发。

2. 初学者常犯的错误

      对于习惯'项目'的人来说,当程序被修改保存后,即可直接切换至浏览器进行测试。但由于MVC需以'网址'的项目类型来开发,所以当程序被修改之后,都要先手动生成项目,才能将修改的结果编译进'bin'目录下组建中,这样才可以切换到浏览器测试,否则所做的修改都不会反映到页面上。

3. 小心使用Request对象和Response对象

      虽然在Controller中可以访问Request对象,但对于从客户端传来的QueryString或Form数据,建议不要通过Request对象取得,以免MVC项目难以维护。

     Response对象也是早期ASP和ASP.NET Web Forms中常用的对象,在controller中建议尽量不要使用。当然,使用它来响应页面内容更要不得。

     不过有规定就例外,只是提醒尽量不要用,并非不能用。如自行开发CAPTCHA图片验证功能时,可能需要通过Response对象响应经过动态运算的图片。

4. 不要在视图中编写过多的程序逻辑

       在开发MVC视图时,一定要尽可能的简化逻辑。不要将过多的商业逻辑写在代码里。

 

二、改良MVC项目

1. 使用视图数据模型

    上一篇中的留言板中,因为先前在 MvcGuestbook.edmx文件创建的'留言板'数据模型包含了5个字段,但是'id'与'建立时间'这两个字段在存储留言中用不到。这样,通过动作窗口接收数据时会有一定的安全风险。所以一些开发,针对一些有特殊目的的窗口或字段,会采用自定义模型的方式来定义。

TIP : 通过'Entity Framework'生成的'Model.留言板'类当成ViewModel使用,若save动作设定的参数类型为'Model.留言板',而且直接将接收到的对象保存到数据库中的话,原本预期只会收到3个参数,但黑客如果知道其他字段的名称(例如创建时间),就可能会多输入一个Form数据,进而复制进你的数据库,并调过字段的默认值。这样,数据库就被注入数据了。

      此类数据模型大多专用于视图中,也称为视图数据模型,即ViewModel。下面是ViewModel的创建过程。

      首先,在'Models'目录下新建一个数据类型(也就是一般的C#类),并将其命名为'GuestbookForm.cs',如图:

       由于留下足迹窗口中只有3个字段,所以在此类中要定义3个属性。具体如下:


1 namespace MvcApplication1.Models
2 {
3     public class GuestbookForm
4     {
5         public string name { get; set; }
6         public string Email { get; set; }
7         public string content { get; set; }
8     }
9 }  

       修改'/Views/Guestbook/Write.aspx'页面的"<% @page...%>"语句,将Inherits属性修改成强制类型,并将ViewPage的属性改为输入MvcApplication1.Models.GuestbookForml类,示例如下。注意,控制器的"return View();"语句不需要修改。


Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.GuestbookForm>"  

      接下来修改原程序中 '<%=Html.Label("name") %>'或'<%=Html.TextBox("name") %>'为MVC2.0新建的强制类型HTML辅助方法,如图,在此过程中还可以利用IntelliSense来编写程序,而且不必担心把字段名称写错。

NOTE: "Html.LabelFor(x=>x.name)"语句中的"x=>x.name"又称为Lambda表达式,是C#3.0/4.0提供的一种机制。

      至于最后输出到浏览器的页面,还是跟之前一模一样。

      接下来我们修改Save()动作。先回忆一下原来的声明,具体如下:


public ActionResult Save(string name,string Email,string content)  

     将以上代码修改如下:


public ActionResult Save(Models.GuestbookForm data)  

     我们将原来的3个参数改成只剩下一个,使用的一样是之前提到过的Model Binder机制。使用这个机制,将自动通过QueryString()方法或Form()方法传来的参数找到对应的强制类型中的属性。只要名称对上了,该机制就会把数据放入该对象的属性中。

      此时,Write视图和Save动作已经在无形中联系起来了,而且使用的是同一个数据模型。这种为了视图而另外定义的数据模型称为视图数据模型(ViewModel),修改完成的程序代码如下:


 1 [HttpPost]
 2         public ActionResult Save(Models.GuestbookForm data)
 3         {
 4             MvcApplication1.Models.GuestbookEntities db = new Models.GuestbookEntities();
 5 
 6             db.AddTo 留言板(new Models.留言板()
 7             {
 8                name =data.name,
 9                Email=data.Email,
10                content=data.content,
11                dtime=DateTime.Now
12 
13             });
14             
15             db.SaveChanges();
16             ViewData["name"] = data.name;
17             ViewData["Email"] = data.Email;
18             ViewData["content"] = data.content;
19 
20             return View();
21         }  

      这段程序代码跟之前差不多,只是参数变少了。但Write视图与Save地址共享用一个ViewModel及用强制类型的方式开发项目有着非常高的价值。如果日后数据库字段名称被修改了,通过VS2010内置的重构机制,将能更有效的针对整个项目进行字段名称的替换。

三、使用窗口验证功能

      好比避免之前留言为空就直接提交到数据库的情况。MVC内置了数据验证机制,只要搭配ViewModel及NET 5 SP1,或者.NET 4.0提供的Data Annotations的函数库,就能定义数据验证规则,同时实现客户端的验证与服务器端的验证了。

      要让GuestbookForm这个ViewModel在使用时能验证'姓名'与'内容'字段为必填项,而且希望当用户输入E-mail数据时能验证其格式,可以通过Data Annotations函数库的声明设定将这些功能应用在ViewModel上。以下是应用Data Annotations函数库的程序代码,可以看出,这里只是多加载了System.ComponentModel.DataAnnotations命名空间和新建了几个属性(Attribute)而已。暂时看不懂,没关系,先看看名字。猜猜用途。

 


 1 using System.ComponentModel.DataAnnotations;
 2 
 3 namespace MvcApplication1.Models
 4 {
 5     public class GuestbookForm
 6     {
 7         [Required]
 8         public string name { get; set; }
 9         [DataType(DataType.EmailAddress)]
10         [RegularExpression(@"^[a-z0-9\._%+-]+@[a-z0-9\.-]+\.([a-z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|asia|jobs|museum)$")]
11         public string Email { get; set; }
12         [Required]
13         public string content { get; set; }
14     }
15 }  

 

      利用ModelState.IsValid 验证,可以通过数据模型绑定进来的数据是否符合ViewModel字段验证的要求,如果验证失败,ModelState.IsValid验证就会返回"false"值,并转到"留下足迹"页面,如下:


 1  [HttpPost]
 2         public ActionResult Save(Models.GuestbookForm data)
 3         {
 4 
 5             if (!ModelState.IsValid)
 6             {
 7                 return RedirectToAction("Write");
 8             }
 9             MvcApplication1.Models.GuestbookEntities db = new Models.GuestbookEntities();
10 
11             db.AddTo 留言板(new Models.留言板()  

至此,我们已经完成了服务器验证的设置工作,接着来看MVC是如何让实现"客户端JavaScript验证"机制的,一共有一下3个步骤。

       Step01:打开"/View/Shared/Site.Master"文件,在"<head>…</head>"标记之间添加以下3个项目内置的javascript文件。


    <script src="http://www.cnblogs.com/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
    <script src="http://www.cnblogs.com/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
    <script src="http://www.cnblogs.com/Scripts/MicrosoftMvcValidation.js" type="text/javascript"></script>  

       Step02:在"<%using (Html.BeginForm("save",RouteData.Values["controller"].ToString())) {%>"语句之前加入以下声明,以启用客户端验证功能。


 <%=Html.EnableClientValidation(); %>  

      TIP:若在一个页面中有两个或者两个以上的窗口需要进行验证," <%=Html.EnableClientValidation(); %>"语句必须出现在第一个Html.BeginForm声明之前,否则验证将无法执行。

      若要使用" <%=Html.EnableClientValidation(); %>"语句验证功能,必须使用Html.BeginForm声明窗口,用户自行编写的<form>标签无法正常使用此功能。

       Step03: 添加字段验证失败时要显示的错误提示信息。

        首先,添加所有验证失败结果的Html.ValidationSummary()方法,示例如下:


 <%=Html.ValidationSummary() %>  

        为每个字段加上ValidationMessageFor()方法,以显示验证失败的错误提示,示例如下:


 1       <%=Html.LabelFor(x => x.name) %>
 2       <%=Html.TextBoxFor(x => x.name) %>
 3       <%=Html.ValidationMessageFor(x=>x.name) %>
 4       <br />
 5       <%=Html.LabelFor(x=>x.content) %>
 6       <%=Html.TextBoxFor(x=>x.content)%>
 7       <%=Html.ValidationMessageFor(x=>x.content) %>
 8       <br />
 9       <%=Html.LabelFor(x=>x.Email) %>
10       <%=Html.TextBoxFor(x=>x.Email)%>
11       <%=Html.ValidationMessageFor(x=>x.Email) %>
12       <br />  

       完成以上3步,调试即可开始测试。

       HTML4.01标准规定的命名规则如下:

  • 首字必须是英文字母(A~Z、a~z)。
  • 首字后面可以是英文字母(A~Z、a~z)、数字(0~9)、减号(-)、下划线(_)、冒号(:)、小数点(.)。

      若有中文名称,可以选中右键然后选取"重建"——"重新命名"选项,或将键盘光标移至该属性名称处,再按下【F2】功能键,都能快速更改属性名称。如图:

四、避免用户重复发送信息

      目前留言板中后会停留在"储存留言"页面,如果此时用户按下了浏览器的"刷新"按钮,将导致窗口重复发送信息,那么在数据库中就会有两条重复的数据。为解决这个问题,PRG(Post-Redirect-Get)样式的概念,是许多网站经常使用的技巧之一。当遇到需要传送的窗口数据的情况下,会先通过HTTP POST请求送出数据;在处理完数据之后,立即转向(Redirect)另一个网址;最后通过HTTP GET请求取得跳转后的页面。在此,修改Save动作,让Save动作不再显示结果页面,而是直接转向Result动作。步骤如下:

      Step01: 删除下列程序代码。

 


1             ViewData["name"] = data.name;
2             ViewData["Email"] = data.Email;
3             ViewData["content"] = data.content;
4 
5             return View();  

 

      Step02: 在删除的程序代码处插入如下语句:


 return RedirectToAction("Result");  

      Step03: 删除"/Views/Guestbook/Save.aspx"页面。

      Step04: 新建Result动作,示例如下:


      public ActionResult Result()
        {
            return View();
        }  

       若要之前Save动作接收到的GuestbookForm类的数据传递给Result视图,以显示用户输入的摘要,这是就必须使用TempData机制来传递这种只会用到"1次"的数据。

      TempData是一个Directory对象,它与ViewData很像,但非常特殊。所有存储在TempData中的数据只能被参考一次,用过之后数据就会被清空。可以利用TempData的特性,将Save动作接收到的GuestbookForm类的数据传递给Result动作。修改Save动作的程序代码,如下:


 TempData["LastPostGuestbookFormData"] = data;  

      Step05: 修改Result动作,程序代码如下:


1      public ActionResult Result()
2         {
3             if (TempData["LastPostGuestbookFormData"] == null)
4             {
5                 return RedirectToAction("Index");
6             }
7             var model = (Models.GuestbookForm)TempData["LastPostGuestbookFormData"];
8             return View(model);
9         }  

      Step06: 新建Result动作视图。新建一个强类型视图,并选取适当的视图数据类型和视图内容之后,即可选取"Details"选项来显示单笔数据,如图:

       通过"视图内容"选项可以创建大部分的程序代码,只稍加修改,就可以得到我们需要的网页,示例如下:


 1 <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.GuestbookForm>" %>
 2 
 3 <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
 4     留言成功
 5 </asp:Content>
 6 <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
 7     <h2>留言成功</h2>
 8     <fieldset>
 9         <legend>Fields</legend>
10              
11         <div class="display-label">name</div>
12         <div class="display-field"><%: Model.name %></div>      
13         <div class="display-label">Email</div>
14         <div class="display-field"><%: Model.Email %></div>      
15         <div class="display-label">content</div>
16         <div class="display-field"><%: Model.content %></div>
17         
18     </fieldset>
19     <p>
20         <%: Html.ActionLink("Edit", "Edit", new { /* id=Model.PrimaryKey */ }) %> |
21         <%: Html.ActionLink("回到留言清单", "Index") %>
22     </p>
23 
24 </asp:Content>  

      再次运行,打开浏览器进行测试,留言成功后就会跳转到"http://localhost:1309/Guestbook/Result"页面,并显示上一页中GuestbookForm类的内容。如图:

      如果此时我们按下"刷新"按钮,由于"TempData["LastPostGuestbookFormData"]"语句已被删除,所以网页就会指向"http://localhost:1309/Guestbook"显示"留下足迹"的页面。

 

     

 

转载于:https://www.cnblogs.com/Eleanore/archive/2012/11/21/2780467.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MVC笔记 MVC注意事项及优化 的相关文章

  • 7天学完Spring:AOP实战,SpringMVC统一处理

    目录 前言 一丶用户登录权限效验 lt 1 gt 最初用户登录验证 lt 2 gt Spring AOP 用户统一登录验证的问题 lt 3 gt 拦截器 拦截功能演示 lt 4 gt 拦截器原理 lt 5 gt 统一访问前缀添加 二丶统一异
  • Code First Migrations更新数据库结构的具体步骤

    Code First Migrations更新数据库结构的具体步骤 作者 寒羽枫 cityhunter172 http blog csdn net cityhunter172 article details 8062420 我对 CodeF
  • 为什么MVC不是设计模式?

    为什么MVC不是设计模式 mvc不是设计模式 而是设计模式的组合 更像是架构 mvc更像是观察者模式 策略模式 组合模式的组合 model表示应用的数据模型 view处理屏幕上展现给用户的内容 当一个model变化时 与它对应的模块发出通知
  • SpringBoot框架

    目录 1 1 简介 1 2 特性 1 3 四大核心 2 springboot入门案例 2 1 SpringBoot 项目开发步骤 2 2 创建一个 Spring MVC 的 Spring BootController 2 3 分析 2 4
  • 手写Spring框架(三)

    这部分目标是MVC 主要完成3个重要组件 HandlerMapping 保存URL映射关系 HandlerAdapter 动态参数适配器 ViewResolvers 视图转换器 模板引擎 SpringMVC核心组件执行流程 相对应的 用以下
  • dao层代码

    dao层 数据接口层 方法层 介于业务逻辑层和数据库之间 进行数据的访问和操作 在实际业务处理过程中 往往需要进行多次数据库的访问 这些访问性质往往是相同的 采用Dao层可以将对数据库访问进行封装 避免经行重复性数据库访问开发操作 同时降低
  • 网站发布一般步骤以及解决方法

    1 在D盘 随便一个地方 新建文件夹 2 在vs项目中点击发布弹出对话框 3 配置文件选择自定义 4 下一步 Publish method 选择file system 5 target location选择第一步创建的文件夹 6 下一步 f
  • 【设计模式】MVC 模式

    MVC 模式代表 Model View Controller 模型 视图 控制器 模式 这种模式用于应用程序的分层开发 Model 模型 模型代表一个存取数据的对象或 JAVA POJO 它也可以带有逻辑 在数据变化时更新控制器 View
  • Head First的MVC之歌(英文版)

    MVC之歌 歌名 模型 视图 控制器 ModelViewController 词曲 James Dempsey https pan baidu com s 1PXDVDqRQVpKcZ1bQwCLNLQ 请大佬 翻译并唱 出来
  • spring mvc中log4j的配置与使用

    原文地址 http rockelixir iteye com blog 1902352 如果使用spring插件创建一个spring template project 它会默认带log4j 只要改下log4j的配置就可以使用了 如果自己创建
  • Spring系列——Spring MVC配置文件

    Spring系列 Spring MVC配置文件 一 前端控制器DispatcherServlet 二 RequestMapping注解 1 使用方法 1 1 标注在方法上 1 2 标注在类上 2 RequestMapping注解的属性 3
  • Bootstrap弹出模态框的运用

    作者 张铭标 撰写时间 2019年 6月3日 Bootstrap模态框主要分为三部分 modal header modal body modal footer 在使用之前需要引入一些插件 bootstrap bundle js jquery
  • 干货丨什么是虚拟化技术?虚拟化常见架构

    在计算机中 虚拟化 英语 Virtualization 是一种资源管理技术 是将计算机的各种实体资源 如服务器 网络 内存及存储等 予以抽象 转换后呈现出来 打破实体结构间的不可切割的障碍 使用户可以比原本的组态更好的方式来应用这些资源 这
  • ABP 框架官网学习资料

    ABP是 ASP NET Boilerplate Project ASP NET样板项目 的简称 新思想 新技术 新架构 更好更快的开发现代ASP NET应用程序 ASP NET Boilerplate是一个用最佳实践和流行技术开发现代WE
  • 关于我写了三万字博客后悔了好久这件事之第二个三万字GUI(swing)

    目录 简介 使用Swing的优势 Swing的特征 Swing基本组件的用法 Swing组件层次 AWT组件的Swing实现 简单了解swing JFrame 弹窗 标签 面板 按钮 3 6 列表 3 7 文本框 JTree TreeMod
  • Handler和Controller的区别

    以前一直以为这两个概念貌似是没有太大的区别 调研发现还是有一些区别的 Handler HandlerMapping接口实现从URL映射到请求处理程序bean 支持映射到bean实例和bean names Controller Base Co
  • MVC三层架构

    1 什么是MVC Model View Controller 模型 视图 控制器 模型就是Java对应数据库的那些字段 实体类 视图 就是JSP页面 控制器 就是Servlet负责跳转页面 Controller作用 Controller其实
  • html理解MVC模型与MVVM模型底层实现

    一 MVC模型的底层实现 1 1 相关代码 div div
  • 基本的Java的MVC入门案例

    概念 MVC Model View Controller 模型 视图 控制器 他是一种专门设计web程序的模式 高内聚 低耦合 高内聚 专人干专事 低耦合 让类与类之间的关系不能太紧密 模型 Model 是应用程序中与处理应用程序数据逻辑的
  • MVC三层架构

    1 MVC三层架构 MVC Model View Controller 是一种常见的软件设计模式 用于组织和管理应用程序的代码和逻辑 它将应用程序分为三个主要部分 模型 Model 视图 View 和控制器 Controller 每个部分都

随机推荐