zoukankan      html  css  js  c++  java
  • MVC3课程中的几个问题整理

    这是几个小问题,整理出来给大家参考

    1. 如何为不同类型的属性设置不同的编辑界面

    备注:这个实例的源代码,可以通过这里下载 MvcApplicationEditTemplate.rar

    我们探讨到了针对不同的属性,MVC3其实可以专门定制不同的编辑界面。这个概念,其实早在MVC出来之前,就曾经有过。之前有一个Dynamic Data的网站模板 ,里面大致也是用到了所谓的编辑器模板(FieldTemplates)的概念。

    我们可以大致看一眼之前的做法

    image

    注意,Dynamic Data这个模板,是基于Web Forms实现的一个应用架构。这里不作进一步展开,如果有兴趣的朋友,可以参考:http://msdn.microsoft.com/en-us/library/ee845452.aspx

    提一下Dynamic Data,是希望给大家一个初步印象,确实可以针对不同类型的字段,设置不同的界面来编辑或者显示。MVC中也提供了这样的机制。

    下面我们来做一个常见的例子,我们希望那些类型为DateTime的属性,在页面上编辑的时候,自动调用jquery的一个日历效果让用户可以选择,而不是简单的一个文本框。

    准备一个业务实体类型(Employee)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace MvcApplicationEditTemplate.Models
    {
        public class Employee
        {
            public int ID { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public DateTime Birthday { get; set; }
        }
    }

    准备一个HomeController

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace MvcApplicationEditTemplate.Controllers
    {
        public class HomeController : Controller
        {
            //
            // GET: /Home/
    
            public ActionResult Index()
            {
                var emp = new Models.Employee();
    
                return View(emp);
            }
    
        }
    }
    

    为这个Action生成一个Edit视图

    @model MvcApplicationEditTemplate.Models.Employee
    
    @{
        ViewBag.Title = "Index";
    }
    
    <h2>Index</h2>
    
    
    
    @using (Html.BeginForm()) {
        @Html.ValidationSummary(true)
        <fieldset>
            <legend>Employee</legend>
    
            @Html.HiddenFor(model => model.ID)
    
            <div class="editor-label">
                @Html.LabelFor(model => model.FirstName)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.FirstName)
                @Html.ValidationMessageFor(model => model.FirstName)
            </div>
    
            <div class="editor-label">
                @Html.LabelFor(model => model.LastName)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.LastName)
                @Html.ValidationMessageFor(model => model.LastName)
            </div>
    
            <div class="editor-label">
                @Html.LabelFor(model => model.Birthday)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Birthday)
                @Html.ValidationMessageFor(model => model.Birthday)
            </div>
    
            <p>
                <input type="submit" value="Save" />
            </p>
        </fieldset>
    }
    
    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>
    

    注意看这里的语法:EditorFor。这是MVC比较推荐的做法,我发现不少朋友可能还是习惯自己去些input,但我个人觉得那不是一个很好的做法。

    预览效果

    image

    我们的需求就是,将Birthday下面这个文本框定制一下,让他可以自动显示出来一个日历。(我们将采用jquery ui来实现)

    添加一个EditorTemplate

    由于Birthday属性是DateTime类型,所以我们可以针对这个类型设计一个编辑器模板。为了共享,我们可以将这个模板放在Shared目录下面

    image

    请注意,这里的目录名必须叫做:EditorTemplates。那个模板的名称也必须叫DateTime.cshtml。 再一次领教了MVC中约定胜于配置的特性吧。

    @model System.DateTime
    @Html.TextBox("",ViewData.TemplateInfo.FormattedModelValue,new {date_picker=true})
    

    在这个文件中,我们只需要指定两行代码。(这是Razor表达式语法),从上面的语法可以看出,我们其实还是放了一个文本框(TextBox),但这里的关键在于,我们会通过jquery来给这个文本框添加特效。

    添加一个jscript文件(EditorBehavior.js)

    /// <reference path="jquery-1.5.1-vsdoc.js" />
    $(function () {
        $(":input[date-picker]").datepicker();
    });
     

    在视图中引入这个脚本文件

    @model MvcApplicationEditTemplate.Models.Employee
    
    @{
        ViewBag.Title = "Index";
    }
    
    <h2>Index</h2>
        <script src="@Url.Content("~/Scripts/jquery-ui-1.8.11.js")" type="text/javascript"></script>
        <script src="@Url.Content("~/Scripts/EditorBehavior.js")" type="text/javascript"></script>
    
    @using (Html.BeginForm()) {
        @Html.ValidationSummary(true)
        <fieldset>
            <legend>Employee</legend>
    
            @Html.HiddenFor(model => model.ID)
    
            <div class="editor-label">
                @Html.LabelFor(model => model.FirstName)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.FirstName)
                @Html.ValidationMessageFor(model => model.FirstName)
            </div>
    
            <div class="editor-label">
                @Html.LabelFor(model => model.LastName)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.LastName)
                @Html.ValidationMessageFor(model => model.LastName)
            </div>
    
            <div class="editor-label">
                @Html.LabelFor(model => model.Birthday)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Birthday)
                @Html.ValidationMessageFor(model => model.Birthday)
            </div>
    
            <p>
                <input type="submit" value="Save" />
            </p>
        </fieldset>
    }
    
    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>
    

    最后预览得到的效果就是下面这样。按照这样的思路,我们还可以给其他类型的属性指定编辑器模板。

     

    image

    这个实例的源代码,可以通过这里下载 MvcApplicationEditTemplate.rar

    2. 为什么脚本移动位置之后,页面的样式变化了

    这是一个小问题,我们先来看一下默认情况下MVC项目的样式

    image

    这个布局和样式,是在_layout.cshtml中定义好的

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>@ViewBag.Title</title>
        <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
        <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
        <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
    </head>
    <body>
        <div class="page">
            <header>
                <div id="title">
                    <h1>
                        My MVC Application</h1>
                </div>
                <div id="logindisplay">
                    @Html.Partial("_LogOnPartial")
                </div>
                <nav>
                    <ul id="menu">
                        <li>@Html.ActionLink("Home", "Index", "Home")</li>
                        <li>@Html.ActionLink("About", "About", "Home")</li>
                    </ul>
                </nav>
            </header>
            <section id="main">
                @RenderBody()
            </section>
            <footer>
            </footer>
        </div>
    </body>
    </html>
    

    出于网站设计优化的考虑,我们知道应该尽可能地将javascript的引用放在页面底部。Yahoo有一个专门的文章讲这方面的内容:Best Practices for Speeding Up Your Web Site

    所以,你可能会尝试将脚本移动到footer里面,例如下面这样

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>@ViewBag.Title</title>
        <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    </head>
    <body>
        <div class="page">
            <header>
                <div id="title">
                    <h1>
                        My MVC Application</h1>
                </div>
                <div id="logindisplay">
                    @Html.Partial("_LogOnPartial")
                </div>
                <nav>
                    <ul id="menu">
                        <li>@Html.ActionLink("Home", "Index", "Home")</li>
                        <li>@Html.ActionLink("About", "About", "Home")</li>
                    </ul>
                </nav>
            </header>
            <section id="main">
                @RenderBody()
            </section>
            <footer>
                <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
                <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
            </footer>
        </div>
    </body>
    </html>
    

    看起来很好,但是再次打开网站的话,就会发现网页的样式有些问题

    image

    这是为什么呢?原因是MVC3默认使用了HTML 5的语法来构建页面,目前HTML 5因为还没有成为事实上的标准,所以使用了一个专门的javascript库来提供支持。这个javascript库就是:modernizr-1.7.min.js, 这是一个开源的作品,请参考这里 http://www.modernizr.com/

    在页面中用到的header,section,footer这类的tag其实是html 5专用的,所以如果上面这个脚本没有预先加载,可能显示的时候,就会有些问题。

    所以,我们应该将modernizr-1.7.min.js放在header里面去。这样就和谐了

    image

    值得一说的是,这个库只有10KB左右,所以将它放在header里面对性能影响很小。

    我们还可以使用微软提供的CDN功能,尽可能地减少用户需要下载的javascript的体积。关于CDN,请参考这里:http://www.asp.net/ajaxlibrary/cdn.ashx

    3.Remote验证

    MVC3提供了一个新增的数据验证功能,叫做Remote验证,意思是可以利用客户端javascript,发起异步的请求,调用服务器代码进行验证。这个功能很不错,例如有一个页面提供用户输入用户名进行注册,我们经常需要检测用户名是否已经被别人占用。这种验证显然是无法在客户端直接提供,而是需要利用服务器代码来实现。

    下面来看一个例子

    首先,我们要为类型定义Annotation,需要注意的是,Remote这个Annotation是MVC专用的,所以要using System.Web.Mvc

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.ComponentModel.DataAnnotations;
    using System.Web.Mvc;
    
    namespace MvcApplicationEditTemplate.Models
    {
        public class Employee
        {
            public int ID { get; set; }
            [Required]
            [Remote("IsNameValid","Home")]
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public DateTime Birthday { get; set; }
        }
    }

    这里指定了一个远程验证用的Controller(Home)和Action(IsNameValid)

    所以,接下来我们准备这样一个Action

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace MvcApplicationEditTemplate.Controllers
    {
        public class HomeController : Controller
        {
            //
            // GET: /Home/
    
            public ActionResult Index()
            {
                var emp = new Models.Employee();
    
                return View(emp);
            }
    
    
            public ActionResult IsNameValid(string FirstName)
            {
                if(FirstName == "ares")
                {
                    return Json(true, JsonRequestBehavior.AllowGet);
                }
                return Json("Your name is invalid", JsonRequestBehavior.AllowGet);
            }
    
        }
    }
    

    注意,这里只是做了一个例子,直接比较FirstName是不是等于ares。实际情况下,这里可以执行数据库查询,得到结果。

    还需要注意的是,这里必须返回json的数据,并且必须设置为AllowGet。

    接下来,在视图中,要添加两个脚本引用,如下所示

    image

    远程验证的效果如下

    image

  • 相关阅读:
    The new powerful SQL executing schedule monthly or weekly in DB Query Analyzer 7.01
    热烈庆祝自已厉精13年开发的 DB查询分析器 7.01(最新版本) 在中关村在线本月获得近6000次的下载量
    CentOS7下安装GitLab
    DB查询分析器7.01新增的周、月SQL执行计划功能
    Ubuntu环境下Anaconda安装TensorFlow并配置Jupyter远程访问
    Docker学习笔记4: Docker-Compose—简化复杂容器应用的利器
    Docker学习笔记3:CentOS7下安装Docker-Compose
    CentOS7下安装python-pip
    [Flutter] 音频播放插件 audioplayers 的一个路径坑
    解放双手之自动拉取与推送
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/2285816.html
Copyright © 2011-2022 走看看