• ASP.NETMVC3 pro系列翻译


    asp.netMVC的出现,让前台和后台都得到了一种回归,编程基础扎实的同学学MVC或许要比webform要轻松N倍,你不在为麻烦的控件配置而焦虑,这里只有纯净的前后台代码。刚刚开始学习MVC,所以就加上自己的理解,翻译一些比较好的书籍和同学们一起来分享MVC3的精彩内容。如果有不合适的地方,大家可以指正和指导下我,我会马上修改。英文的资料看起来很容易但是要是用来写成文字,发现远远超过了读三章的时间,今天我几乎写了3.5个小时的博客到后面有点小浮躁,不知道翻译有没有出入,如有不妥大家都可以指正。


    你的第一个MVC应用程序

       领悟一个软件开发框架的最佳方式深入内部并使用它本章中,您将使用ASP.NET MVC框架创建一个简单的数据输入应用程序我们要一步步的让你看到如何构建一个ASP.NET MVC应用程序为了简单易懂,我们将跳过一些技术细节的时刻,但不要担心,如果你是初识MVC,你会发现很多让你感兴趣的在这里我们应用但没有过多的解释(这章的重点不是原理),在后面我们提供各个参考的章节这里你可以找到所有的细节

    创建一个新的ASP.NET MVC项目

    我们将开始在Visual Studio中创建一个新的MVC项目“文件”中选择“新建项目菜单打开新建项目对话框如果您选择网页模板,你会看到MVC 3安装程序ASP.NET MVC 3 Web应用程序创建一个新的项目如图3-1所示

    图3-1在Visual Studio中的MVC 3项目模板

      设置的新项目P名称为artyInvites单击“确定”按钮继续你会看到一个对话框,如图3-2所示要求您选择三种不同类型的MVC项目模板。

        如果仅仅是最低要求的文件和文件夹的MVC 3 应用程序你可以选择创建一个 Empty项目。Internet应用程序“选项创建一个小的示例应用程序,您可以在他的基础上修改和建立自己的应用程序。它包括用户注册和认证,导航和一致的视觉风格。 Intranet应用程序选项是类似于Internet应用程序,但其设计中使用了对用户进行身份验证域/ Active Directory基础结构的环境。在本章中,我们将让事情变得简单易懂。选择“Empty选项,取消选中的HTML5语义标记选项,并单击“确定”以创建新的项目。

      注意图3-2中模板选项你可以看到一个下拉菜单,在这里你可以指定需要的视图引擎正如我们在第1章MVC 3包含一个新的Razor视图引擎和改进的ASPX视图引擎,这是我们将在本书中群不全部使用Rozor我们建议你和我们一样这么选择但是如果你想使用常规的ASP.NET视图引擎(又称为ASPX引擎您也可以选择
      一旦在Visual Studio创建的项目,你会在VS的“解决方案资源管理器”窗口看到一些文件和文件夹结构这是默认的MVC 3项目结构可以尝试运行
    现在应用程序“调试”菜单选择开始调试如果提示您启用调试时,只要按一下“确定”按钮)。您可以看到图3-3的结果应为我们开始使用了Empty项目模板,应用程序不包含任何内容所以我们可以看到一个404 Not Found错误

    图3-3。试图运行一个空项目
      当你完成后,一定要停止调试关闭显示错误浏览器窗口(当然也可以不关闭下次生成项目后刷新浏览器)回到Visual Studio“调试”菜单选择停止调试MVC架构添加一个控制器控制器处理传入的请求ASP.NET MVC控制器简单C#通常继承System.Web.Mvc.Controller,这是asp.netMVC内置控制器基类)。每个公共方法被称为控制器的action方法,这意味着你可以通过一些URL从Web调用和执行一项操作(action) MVC约定是把
    所有的控制器放在名为Controllers的文件夹中,这是我们创建项目时,由Visual Studio创建控制器
    你并不需要遵循本约定或其他大多数MVC约定我们建议你这样操作并不是简单的因为这将有助于你理解这本书中的例子

       右键单击Controllers文件夹Visual Studio解决方案资源管理窗口,并弹出的菜单选择“添加”,然后控制器添加一个控制器到我们的项目中,如图3-4所示

    图3-4。添加控制器的MVC项目
      当出现添加控制器对话框时,将名称设置为HomeController的,如图3-5所示。这又是一个约定:我们给控制器的名称应该是描述性和以Controller结尾

    图3-5设置为控制器的名称
      Scaffolding options中给我们预制了控制器使用常见功能模板我们不打算使用此功能,因此要确保在“模板”菜单中选择Empty controller如图所示。    注意:如果你没有看到,因为它是图3-5所示添加控制器对话框可能忘了安装工具更新MVC 3有关详细信息,参阅第2章

      单击“添加按钮创建一个控制器。Visual Studio将在Controller文件夹中创建一个新的名为HomeController.csC#代码文件打开它进行编辑时,你可以看到,这个被称为HomeController的类它是在System.Web.Mvc命名空间下定义的编辑这个文件中的代码,如下3-1。

    Listing 3-1. 修改 HomeController 类

    复制代码
    using System.Web.Mvc; 
     
    namespace PartyInvites.Controllers { 
     
            public class HomeController : Controller { 
             public string Index() { 
                return "Hello, world"; 
            } 
        } 
    } 
     
    复制代码

      当然这不足以令人兴奋的但对刚刚学习MVC的童鞋这是一个很好的开端我们创建了一个名为为Indexaction方法,它会返回字符串“Hello,world”再次运行该项目(从Visual Studio的“调试菜单选择“启动调试)浏览器将显示的结果。如图3-6所示

    图3-6 浏览器输出结果

    了解路由
      除了模型,视图和控制器,MVC应用程序也使用ASP.NET路由系统决定如何将URL映射到特定的控制器和action中
      当Visual Studio创建的MVC项目它会添加一些默认路由,您可以使用下面的任何一个URL请求他们将被引导到了HomeControllerIndex action

    •  / 
    •  /Home 
    •  /Home/Index

    浏览器请求http://yoursite/http://yoursite/Home,将调用HomeController的Index方法输出字符串“Helloworld是一个很好的遵循MVC约定例子在这种情况下我们将一个名叫HomeController的控制器,这将是我们的MVC应用程序的起点一个名叫HomeController的,这将是我们的MVC应用程序的起点假设我们遵循了这一约定Visual Studio会创建一个新的项目缺省路由我们URLS前面的列表中得到支持如果我们没有依循惯例我们将需要手动修改的路由指向需要的控制器对于这个简单例子,默认的配置就够了

    提示:您可以通过打开的Global.asax.cs文件查看和编辑您的路由配置在第7章中,您将设置自定义路由,并在第11章会学到更多关于路由可以什么

    渲染网页
     前面的例子不是输出HTML而是简单的字符串“Hello,world”我们需要创建一个视图浏览器请求,响应HTML。
    创建和渲染视图
    我们需要做的第一件事情就是修改我们的索引中的操作方法,如清单3-2所示。
    清单3-2。修改控制器渲染视图

    复制代码
    using System.Web.Mvc; 
     
    namespace PartyInvites.Controllers { 
     
        public class HomeController : Controller { 
     
            public ViewResult Index() { 
                return View(); 
            } 
        } 
    } 
     
    复制代码

     清单3-2以粗体显示当我们返回一个ViewResult对象从一个action方法我们我们通过调用视图的方法创建的ViewResult
    (不带任何参数)发出指令让
    MVC渲染视图这将使MVC为该action呈现的默认视图如果您运行的应用程序你可以看到MVC框架试图找到一个默认的视图显示的错误信息如图3-7所示

    如图3-7所示。 MVC框架试图找到一个默认的视图
        错误消息是最有帮助的。它不仅解释无法为某个action方法找到一个MVC视图,这又是一个很好的MVC约定view与action方法的命名约定。我们的action方法称为Index,你可以从图3-7中看到的MVC正试图在“视图文件夹中找到不同的文件所有相同名称。
      创建一个视图,用鼠标右键单击在HomeController.cs代码文件的操作方法(无论是在方法的名称或内部的方法体),从弹出的菜单中选择添加视图。这将打开添加视图“对话框,如图3-8所示。

        取消选中“使用布局或母版页。我们不使用布局,在这个例子中,但我们会看到他们在第5章中使用。点击“添加”按钮,Visual Studio将在 View/ Home创建一个新的视图文件Index.cshtml。如果你回头看看图3-7中的错误信息,你会看到,被搜查的路径之一与我们刚创建的文件相匹配。
         提示:CSHTML的文件扩展名表明他是一个由Razor视图引擎处理的。老版本的MVC依靠ASPX视图引擎,视图文件.aspx扩展名。
        打开Index.cshtml文件进行编辑。这个文件主要包含HTML。 其中有一段代码块如下:

    @{ 
        Layout = null; 
    } 

       这是一个将被Razor视图引擎解释的代码块。它只是告诉Razor视图引擎,我们选择不使用母版页。

    如图Index.cshtml文件在清单3-3中所示

    复制代码
    @{ 
        Layout = null; 
    } 
     
    <!DOCTYPE html> 
     
    <html> 
    <head> 
        <title>Index</title> 
    </head> 
    <body> 
        <div> 
            Hello, world (from the view)         
        </div> 
    </body> 
    </html> 
    复制代码

      添加一些简单的信息选择“开始”,从“调试”菜单中进行调试运行并测试应用程序。您应该会看到类似图3-9。

      当我们第一次创建Index的action方法,他除了输出简单的字符串返回给浏览器什么都没干现在,方法返回一个ViewResult类型的对象,指示MVC渲染视图,并返回HTML我们没有并没有指定MVC视图应该怎么做,所以使用的命名约定自动匹配。相应的View具有和controller文件夹中的action方法一样的名称——~/Views/Home/Index.cshtml.我们可以让action方法返回其他结果(除了字符串的ViewResult对象)例如,如果我们返回RedirectResult浏览器重定向到另一个URL如果我们返回HttpUnauthorizedResult我们强制用户登录他们都继承自ActionResult类action result 体系让我们封装和复用常见的相应操作更加方便我们将通过这本书告诉更多关于他们复杂的使用

    添加动态输出
      当然,对于整个Web应用程序平台构建动态显示输出来看MVC,准备响应数据是控制器的工作呈现HTML则是视图的工作数据从控制器传递到视图
    数据从控制器传递到视图方法之一通过使用ViewBag对象这是一个Controller基类的成员 ViewBag是一个动态对象,你可以指定任意的属性并使这些值呈现在任何视图清单3-4演示
    以这种方式通过一些简单的动态数据

    复制代码
    Listing 3-4. Setting Some View Data 
    using System; 
    using System.Web.Mvc; 
     
    namespace PartyInvites.Controllers { 
     
        public class HomeController : Controller { 
     
            public ViewResult Index() { 
     
                int hour = DateTime.Now.Hour; 
                ViewBag.Greeting = hour < 12 ? "Good morning" : "Good afternoon"; 
                return View(); 
            } 
        } 
    } 
     
    复制代码

      以粗体显示的语句我们提供的数据的视图。如清单3-5所示。

    复制代码
    Listing 3-5. Retrieving a ViewBag Data Value 
    @{ 
        Layout = null; 
    } 
     
    <!DOCTYPE html> 
     
    <html> 
    <head> 
        <title>Index</title> 
    </head> 
    <body> 
        <div> 
           @ViewBag.Greeting, world (from the view) 
        </div> 
    </body> 
    </html> 
     
    复制代码

        清单3-5是一个Razor代码块,检索保存在的ViewBag的greeting属性。该属性名称没有什么特别的之处,你可以更换任何自定义属性名称(它的作用是相同的)。当然,你可以在视图中以相同的方式获取多个数据值的。

    提示我们并不需要终止Razor代码块。我们以@字符开始,然后添加我们的C#代码。这是Razor一个很好的特性。这样更具可读性,我们不在需要使用烦人的<%和%>标记。

        如果我们再次运行该项目,我们可以看到我们的第一个动态的MVC输出,如图3-10所示。

    创建一个简单的数据录入应用程序

        在本章的剩余部分,我们将通过建立一个简单的数据输入应用程序探讨更基本的MVC功能。在本节我们将加快进度。我们的目标是展示MVC的应用, 所以我们跳过一些的解释是后台是如何工作的的话题。但是不要担心,在后面的章节中,我们将再次深入这些话题。

    设置场景

    我们会想象,一个朋友已经决定举办一个除夕派对,她要我们创建了一个网站,让她受邀者使用电子邮件回复。她要求四个主要特点:

    • 显示有关晚会的一个主页
    • 提交RSVP的表单
    • 验证RSVP的格式,之后将显示一个感谢页面
    • 完成后回函电子邮件

    在下面的章节中,我们将建立在已经创建的MVC项目中,我们在本章开始添加这些功能。通过运用我们在前面的内容中,我们可以添加一些HTML到我们现有的视图来描述party的细节,如清单3-6所示。

     

    复制代码
    Listing 3-6. Displaying Details of the Party 
    @{ 
        Layout = null; 
    } 
     
    <!DOCTYPE html> 
     
    <html> 
    <head> 
        <title>Index</title> 
    </head> 
    <body> 
        <div> 
           @ViewBag.Greeting, world (from the view) 
           <p>We're going to have an exciting party.<br /> 
           (To do: sell it better. Add pictures or something.) 
           </p> 
        </div> 
    </body> 
    </html> 
     
    复制代码

       您运行的应用程序,你会看到party的细节,如图3-11所示。

    设计一个数据模型
    在MVC中,M代表的是模型,它是应用程序最重要的的一部分。该模型是将真实世界的对象,过程和规则抽象的定义在程序域中通常被称为一个域模型,该模型包含了C#对象已知的域对象),使我们可以在应用程序和方法中对它们进行操作,并通过一些方式可以将其信息回馈给客户端。一个精心设计的模型是一个设计良好的MVC应用程序的开始,现在我们把重点放在添加控制器和视图。
    我们并不需要为PartyInvites应用程序添加一个复杂的模型,这里我们只是用一个简单的名为GuestResponse域模型我们将使用用于负责存储,验证,并确认RSVP。

    添加一个模型类
    MVC的约定是一个模型的类被放置在〜/ Models文件夹解决方案资源管理器窗口右键单击“模型选择”添加弹出的菜单。设置文件名GuestResponse.cs单击“添加按钮来创建类。按照清单3-7编辑类的内容

    提示 您可能已经注意到WillAttend属性一个可为空布尔值,这意味着它可能是truefalse,或者为null。添加验证我们将在后面的章节中解释添加验证理由
    链接操作方法
    我们的应用程序包括了RSVP表单所以我们需要添加一个链接到它我们的Index.cshtml视图清单3-8所示

    复制代码
      Listing 3-8. Adding a Link to the RSVP Form 
    @{ 
        Layout = null; 
    } 
     
    <!DOCTYPE html> 
     
    <html> 
    <head> 
        <title>Index</title> 
    </head> 
    <body> 
        <div> 
           @ViewBag.Greeting, world (from the view) 
           <p>We're going to have an exciting party.<br /> 
         (To do: sell it better. Add pictures or something.) 
           </p> 
           @Html.ActionLink("RSVP Now", "RsvpForm") 
        </div> 
    </body> 
    </html> 
    复制代码

       Html.ActionLink是一个HTML辅助方法。MVC框架集中方便的选择辅助方法的渲染HTML链接,文本输入框,复选框,甚至是自定义的控件。 ActionLink方法有两个参数:第一个是要显示的文本的链接,第二个是要执行的action。当用户点击的链接,您可以看到在图3-12中添加的链接效果。我们将在第15和第16章中讲解HTML辅助方法。

      当你的鼠标放在浏览器中链接上时,你会看到该链接指向ttp://yourserver/Home/RsvpFormHtml.ActionLink方法检查我们的应用程序的URL
    路由配置和执行HomeControls中的名为ResvpForm的action。注意,不同于传统的ASP.NET应用程序,MVCURL对应于物理文件每个action方法都有其自己的URL,MVC使用ASP.NET路由系统把这些urls指向创建的action方法.如果您单击的链接你会看到一个404 Not Found错误.因为我们还没有创建的action方法
    对应的/Home/RsvpFormURL为此,我们要给HomeController类添加一个名为RsvpForm的方法清单3-9所示

    复制代码
    Listing 3-9. Adding a New Action Method to the Controller 
    using System; 
    using System.Web.Mvc; 
     
    namespace PartyInvites.Controllers { 
     
        public class HomeController : Controller { 
             public ViewResult Index() { 
     
                int hour = DateTime.Now.Hour; 
                ViewData["greeting"] = hour < 12 ? "Good morning" : "Good afternoon"; 
                return View(); 
            } 
     
            public ViewResult RsvpForm() { 
                return View(); 
            } 
        } 
    } 
    复制代码

    添加一个强类型的视图
      我们给RsvpForm方法添加的视图但我们会一些调整,我们要创建一个强类型的视图一个强类型的视图的目的是渲染一个特定的域类型,如果我们指定的类型我们使用在这个例子中是GuestResponseMVC可以提供一些有用快捷方式,使其更容易
       注意 做其他事情之前,请确保MVC项目被编译如果您已经创建了GuestResponse类,但没有编译,MVC将无法创建一个强类型的视图对应这种类型
    从Visual Studio生成“菜单选择生成解决方案编译您的应用程序
      右键单击里面RsvpForm方法弹出的菜单选择添加视图添加视图对话框选中创建一个强类型的视图选项,并下拉菜单中选择GuestResponse取消选中“使用布局或母版页,并确保选择Razor引擎布局模板选项设置为空,如图如图3-13所示。

      单击“添加按钮创建新的视图Visual Studio将打开RvspForm.cshtml文件你会看到,它是一个一个@ modelRoazr格式开头HTML文件正如你将看到
    当前这已经是一个强类型的视图,提供的很多的便利
    建立表格
      现在,我们已经创建了强类型的视图,我们可以在RsvpForm.cshtml文件中编写一个HTML表单用于编辑GuestResponse对象。如下清单3-10。

    复制代码
    Listing 3-10.  Creating a Form View 
    @model PartyInvites.Models.GuestResponse 
     
    @{ 
        Layout = null; 
    } 
     
    <!DOCTYPE html> 
     
    <html> 
    <head> 
        <title>RsvpForm</title> 
    </head> 
    <body> 
        @using (Html.BeginForm()) { 
            <p>Your name: @Html.TextBoxFor(x => x.Name) </p> 
            <p>Your email: @Html.TextBoxFor(x => x.Email)</p> 
            <p>Your phone: @Html.TextBoxFor(x => x.Phone)</p> 
            <p> 
                Will you attend? 
                @Html.DropDownListFor(x => x.WillAttend, new[] { 
                    new SelectListItem() {Text = "Yes, I'll be there", Value = bool.TrueString}, 
                    new SelectListItem() {Text = "No, I can't come", Value = bool.FalseString} 
                }, "Choose an option") 
            </p> 
            <input type="submit" value="Submit RSVP" /> 
        } 
    </body> 
    </html> 
    复制代码

     

       对于GuestResponse模型类的每个属性,我们使用一个HTML辅助方法渲染一个合适的HTML input标签。这些方法会让你选择输入元素的属性,涉及到
    使用lambda表达式,例如:
    Html.TextBoxFor(X => x.Phone
      不要担心,如果你不熟悉C#lambda表达式。我们在第5章中提供了一个概述。
      HTML辅助方法生成的HTML生成一个input 元素,设置它的type为text,并设置id和name属性为Phone,而这些都是以的域模型的属性名为准,如下
    属性,如下所示:
    <input id="Phone" name="Phone" type="text" value=""
     
    这个方便的特性依赖于此处的RsvpForom方法对象的视图是强类型的,我们已经告诉过MVC,操作的是GuestResponse类型,我们要渲染这个View。
    另一种替换lambda表达式的方法是使用一个名称相同的字符串类型的属性,例如:
    Html.TextBox(“电子邮件

    我们发现,我们的lambda表达式技术可以防止输错的模型名称和相应的属性。Visual Studio会弹出智能提示我们挑选的合适的并自动完成关联如图3-14所示

        另一种方便的辅助方法是Html.BeginForm,生成一个HTML表单元素并配置回发的操作方法。因为我们还没有传递任何参数给该方法,它会认为我们要回发到相同的URL。一个使用它的绝招是用C#using 声明包装它,例如:

     @using (Html.BeginForm())

    {  

       ...form contents go here...

    }

        通常情况下,这样的应用时,使用的语句确保一个 超出范围对象被及时释放。它常用于数据库操作中,例如,在完成一个查询以确保他们 尽快关闭,(这里的using关键字不同于讲一个外部类用一个命名空间引入到一个类的作用域中的using),而不是丢弃对象, HtmlBeginForm helper在HTML表单元素超出的范围自动将其释放。这意味着该 Html.BeginForm辅助方法创建的表格元素,像这样两个部分:

    <form action="/Home/RsvpForm" method="post">

        形式内容到这里...

    </ FORM>

      不要担心,如果你不熟悉C#对象的处理。这里的关键是演示如何创建使用HTML辅助方法的一种形式。

    提示  ASP.NET WebForm只支持一个服务器端的控件通常注明为<form runat="server">这是一个视图状态数据回传逻辑的容器MVC则不需要这种的形式。我们只需要使用使用普通的HTML标签你可以在一个视图中素心所欲的使用。而不必担心没有视图状态(ViewState)或其他隐藏的表单元素的id值分配错位当您运行应用程序,然后单击“现在RSVP链接你可以看到的形式RsvpForm视图图3-15显示了结果。

     请注意:这不是一本关于CSS网页设计。在大多数情况下,我们将要创建的例子,它的外观可以被描述为乡巴佬(虽然我们喜欢这个词的经典之作,但不是轻蔑)。MVC视图生成非常干净和纯洁的HTML,你可以完全控制他们被分配到的布局元素和类,所以你可以使用设计工具或现成的模板,让你的MVC项目漂亮。

     处理表单
      我们没有告诉MVC的形式发送到服务器时,我们想要做的是什么。就目前情况来看,点击“SubmitRSVP按钮,会清除任何你输入到表单中的值。这是因为,表单回发后只是调用了Home controller中的RsvpFrom方法,告诉MVC再次查看视图.
      注意 输入的数据再次呈现视图时丢失你可能会感到失望如果真是这样,你宁可使用ASP.NETWebForm开发应用程序,因为他有自动保存数据的功能。现在,我们将向您展示MVC如何实现同样的效果接收和处理提交的表单数据我们要做一个聪明事情我们将再添加一个RsvpForm的action方法
      •响应HTTP GET请求方法GET请求是什么浏览器问题通常每次有人点击一个链接这个版本的操作负责显示初始空白表格,当有人第一次访问/Home/       RsvpForm
      •响应HTTP POST请求的方法默认情况下,表单呈现Html.BeginForm()方法提交一个POST请求浏览器这个版本的action负责接收提交的数据,并决定如何处理。
      将GET和POST请求在单独的C#方法处理有助于保持我们的代码整洁,因为这两个方法有不同的责任。这两个action方法调用相同的URL,但MVC会调用适当的方法。
    清单3-11。增加一个action方法来支持POST请求
     
    复制代码
    using System; 
    using System.Web.Mvc; 
    using PartyInvites.Models; 
     
    namespace PartyInvites.Controllers { 
     
        public class HomeController : Controller { 
     
            public ViewResult Index() { 
     
                int hour = DateTime.Now.Hour; 
                ViewData["greeting"] = hour < 12 ? "Good morning" : "Good afternoon"; 
                return View(); 
            } 
             [HttpGet] 
            public ViewResult RsvpForm() { 
                return View(); 
            } 
     
            [HttpPost] 
            public ViewResult RsvpForm(GuestResponse guestResponse) { 
                // TODO: Email guestResponse to the part organizer 
                return View("Thanks", guestResponse); 
            } 
        } 
    } 
     
    复制代码

        我们已经添加了的HTTPGET特性,RsvpForm的action方法。这是告诉MVC,这种方法只能用于GET请求。然后,我们添加了一个重载的方法RsvpForm,其中需要一个GuestResponse类型的参数用应用HttpPost特性。告诉MVC新的方法将处理POST请求。请注意,我们导入了PartyInvites.Models命名空间。所以下面代码中无需类的全限定名。

    使用模型绑定
      第一个重载的RsvpForm的action方法,使用之前相同的View。它产生的形式如图3-15所示。第二个重载是更有趣,因为传入了参数,但考虑到
    该action方法将作为HTTP POST请求的响应被调用,但是GuestResponse类型是一个C#类,怎么怎么进行关联呢?

      答案是绑定Model,这是MVC一个非常有用的功能,即输入的数据进行解析被用来填充的域模型类型的属性的键/值对。这个过程和使用HTML辅助方法相反的,也就是说,当创建的表单数据发送给客户端,我们生成的HTML输入元素的id和name属性的值来自在模型类的属性名。与此相反,与模型的结合,输入元素的名称是
    用于设置模型类的一个实例的属性值,然后将其传递给处理的POST请求的action方法。
      模型绑定是一个强大的和可定制的功能,让我们不再面的琐碎的与HTTP请求,而是让我们的面向C#对象,(不用在处理的Request.Form[]的Request.QueryString[]值。) GuestResponse对象作为参数被传递action方法中自动去填充表单字段的数据。在第17章中我们将深入到模型的bind的细节也包括如何自定义。。。

    渲染视图

      第二个重载的在RsvpForm的action方法,还演示了如何响应一个请求,渲染特定视图。如下面的语句:
      return View("Thanks", guestResponse);

      它通知MVC查找和渲染名为“Thanks”的视图,并传入我们的GuestResponse对象。创建的视图,右键单击里面的其中一个RsvpForm方法,并从弹出的菜单中选择添加视图。设置名称为“Thanks”.

    如图3-16所示。

         我们将创建另外一个强类型的视图,因此在添加视图对话框中,我们选择的视图模型必须与传递给视图中使用的View方法的类一致,所以必须从Modles class下拉列表中选择GuestResponse。确保选择母版页选项没有被选中,视图内容设置为空。单击“添加”创建新的视图。MVC创建了一个新的视图文件,~/Views/Home/Thanks.cshtml.编辑新的视图,如Listing 3-12

    复制代码
    Listing 3-12.  The Thanks View 
    @model PartyInvites.Models.GuestResponse 
     
    @{ 
        Layout = null; 
    } 
     
    <!DOCTYPE html> 
     
    <html> 
    <head> 
        <title>Thanks</title> 
    </head> 
    <body> 
        <div> 
            <h1>Thank you, @Model.Name!</h1> 
            @if (Model.WillAttend == true) { 
                @:It's great that you're coming. The drinks are already in the fridge! 
            } else { 
                @:Sorry to hear that you can't make it, but thanks for letting us know. 
            }     
        </div> 
    </body> 
    </html> 
    复制代码

      Thanks View使用Razor显示基于GuestResponse类的属性值的内容,通过RsvpForm的action方法访问视图。@model运算符指定View的域模型的是强类型的类型。要访问域对象的属性值,我们使用Model.PropertyName。例如,得到的Name属性的值,我们使用,Model.Name。不要担心,如果的Razor语法不熟悉 - 我们将在第5章解释它现在,我们已经创建了Thanks View启动应用程序Visual Studio中,单击“RSVP”链接,之后添加一些数据,并单击“SubmitRSVP“按钮。你会
    看到如图3-17所示的结果(虽然它可能会有所不同,如果你的名字是不是Joe,或者你选择不能参加)。

     

    添加验证
        现在我们为应用程序添加验证。如果我们不这样做,我们的用户可以输入垃圾数据,甚至提交一个空的表单。在MVC应用程序中,验证通常应用在域模型中,而不是在用户接口。这意味着,我们在同一个地方定义我们的验证标准,它在任何地方生效。ASP.NET MVC支持声明System.ComponentModel.DataAnnotations命名空间的属性定义的验证规则。

    清单3-13显示了如何将这些特性应用于到的GuestResponse的模型类。

      上面用粗体显示了验证规则。 MVC检测验证属性,并使用它们来来验证数据模型的绑定过程。请注意,我们导入了包含验证类的命名空间。
      提示如前所述,我们使用了一个可为空的布尔的WillAttend属性。所以我们可以应用必要的验证属性。如果我们用一个普通的布尔值,该值可能是我们通过模型绑定唯一的true或false的,我们将不用去告诉如果用户怎么样选择一个值。可空布尔有三个可能的值:true,false和null。空值将被使用,如果用户还没有选择的一个值,这所需的属性来报告验证错误。我们在我们的控制器类可以使用ModelState.IsValid属性检查验证状态

    清单3-14显示了如何做到这一点

      如果没有验证错误,我们告诉MVC渲染Thanks视图。如果有验证错误,我们重新呈现的RsvpForm之前的视图,并将错误显示给用户我们需要显示给用户,验证错误,我们可以使用Html.ValidationSummary辅助方法,如清单3-15所示。

    如果有没有错误Html.ValidationSummary方法创建一个隐藏的 MVC的占位符,并添加验证属性定义错误消息可以看到这显示图3-18

    注意:如果您使用过ASP.NET WebForm你就会知道,“服务器控件,WebForm通过序列化到__VIEWSTATE的隐藏的表单字段保持状态 ASP.NET MVC模型绑定
    不同于WebForm的服务器控件回发,视图状态概念 ASP.NET MVC注入隐藏的__VIEWSTATE字段到您的渲染HTML页面
    高亮显示验证

        HTML helper方法是创建文本框,下拉框和其他元素的HTML的辅助方法,它有一个非常方便的功能,可用于与模型绑定。同样的机制,可以保留的数据表单中输入的用户也可以用于突出显示个别字段失败验证检查。

      当一个模型类的属性未通过验证,HTML辅助方法会产生轻微不同的HTML。举个例子,这里的HTML是调用Html.TextBoxForX => x.Name产生的
    如果没有验证错误将是如下代码

    <input data-val="true" data-val-required="Please enter your name" id="Name" name="Name"  
    type="text" value="" /> 
     

     当用户没有提供一个值(这是一个验证错误因为我们调用了GuestResponse模型类Name属性Required验证约束)你会看到代码略有不同:

    <input class="input-validation-error" data-val="true" data-val-required="Please enter your  
    name" id="Name" name="Name" type="text" value="" /> 
     

      我们加粗以突出显示的不同之处。这个helper方法添加一个CSS类,称为input-validation-error。不同的辅助方法适用于不同的CSS类,但它们都可以在~/Content/Site.css的样式表中找到。怎么引入该样式表,是这样的:

    <link rel="Stylesheet" href="@Href("~/Content/Site.css")" type="text/css"/> 

      提示:如果已经使用了ASPX视图引擎可以使用指定路径直接使用符号(〜)(如:HREF=“〜/内容/的Site.css依靠视图引擎转换一个URL,浏览器可以按照(如  href="~/Content/Site.css"Razor视图引擎采用不同的方法它要求使用HREF运算符将URL(如HREF   href="@Href("~/Content/Site.css")"在第5章中你可以找到更详细的介绍。

      现在,当用户提交数据将导致验证错误会看到一个更加明显方式展示问题的根源如图3-19所示

    完成示例
      我们的应用程序中最后一个要求我们的朋友,使用电子邮件完成给组织者的回函我们可以通过添加action方法并使用.NET框架中e-mail类来创建和发送电子邮件信息做到这些,不过这里,我们将使用webmail辅助方法MVC框架一部分,但它确实我们完成这个例子的细节,而不用设立其他的发送电子邮件形式
    请注意 我们使用了webmail辅助方法,因为它让我们发送电子邮件消息的变得不费吹灰自理然而通常情况下,我们宁愿把这个功能的放在一个action方法中在第4章中描述了MVC架构模式时我们将解释为什么

    清单3-16  Using the WebMail Helper 

    复制代码
    @model PartyInvites.Models.GuestResponse 
     
    @{ 
        Layout = null; 
    } 
     
    <!DOCTYPE html> 
     
    <html> 
    <head> 
        <title>Thanks</title> 
    </head> 
    <body> 
     
        @{ 
            try { 
                WebMail.SmtpServer = "smtp.example.com"; 
                WebMail.SmtpPort = 587; 
                WebMail.EnableSsl = true; 
                WebMail.UserName = "mySmtpUsername"; 
                WebMail.Password = "mySmtpPassword"; 
                WebMail.From = "rsvps@example.com"; 
     
                WebMail.Send("party-host@example.com", "RSVP Notification", 
                    Model.Name + " is " + ((Model.WillAttend ?? false) ? "" : "not")  
                        + "attending"); 
                 
            } catch (Exception) { 
                @:<b>Sorry - we couldn't send the email to confirm your RSVP.</b>  
            } 
        } 
     
        <div> 
            <h1>Thank you, @Model.Name!</h1> 
            @if (Model.WillAttend == true) { 
                @:It's great that you're coming. The drinks are already in the fridge! 
            } else {             @:Sorry to hear that you can't make it, but thanks for letting us know. 
            }     
        </div> 
    </body> 
    </html> 
     
    复制代码

       我们增加了一个Razor代码块,使用WebMail的辅助方法配置电子邮件服务器,包括服务器名称,服务器是否需要SSL连接,和帐户详细信息。
    一旦我们配置了所有的细节,我们就可以使用WebMail.Send的方法来发送电子邮件。这里我们使用在try ...catch块,如果不发送电子邮件不成功也可以提醒用户。一个更好的方法是如果不能发送电子邮件消息显示一个单独的错误视图而不是在同一个View中显示各用户我们希望保持我们的第一个MVC应用程序的简单易懂(所以暂时不这么做)。

    总结
    在本章中,我们创建了一个新MVC项目用它来构建一个简单的MVC数据输入应用程序,让你一睹MVC框架结构和方法的魅力我们跳过了一些关键的功能(包括Razor语法,路由和自动测试在后面的章节中我们会回头来深入这些主题在下一章中,我们将探讨MVC架构,设计模式技术,并贯穿全书

     
  • 相关阅读:
    poj2253 青蛙
    这代码真是好,真是文艺,转来的
    java.text.MessageFormat
    java多线程的两种实现方式
    javascript with
    面向接口编程
    java 多线程 读写锁
    java 多线程 资源共享
    UML:继承、实现、依赖、关联、聚合、组合
    javascript 语言精粹 学习笔记
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2676011.html
Copyright © 2020-2023  润新知