Programming ASP.NET MVC-Fundamentals of ASP.NET MVC(六)View

          View

          在Asp.net mvc framework里,contorller action如果想显示一个html,会返回一个actionResult类型的ViewResult的实例,然后viewResult渲染内容到客户端。(当渲染view的时候,framework会查找和contrller action名称一致的view。

           比如:homeController

           

public ActionResult Index()
        {
            ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

            return View();
        }
           上面的代码,会返回一个名称为Index的view到客户端。

           Locating Views

           asp.net mvc通过命名约定,使所有的view都位于views文件夹下。更具体地说,asp.net mvc要求view位于的文件夹名要和它相关的controller名称一致。

          就像上面的例如,如果asp.net mvc如果想显示homeContrller的action,它就会在 /Views/Home文件夹下,查找名称为Index的文件。如果它没有找到对应名称的view,它就会在 /Views/Shared文件夹下查找。

             注:/Views/Shared可以用来放置多个controller要用到的view.


            Hello, Razor!

            我们打开view文件,看到的是Razor。

            Razor是一种允许混合代码和内容的语法。虽然它引进了一些新的符号和键值,但是它并不是一种新的语言。而且Razor允许写我们很熟悉的代码,比如说C#或者Visual Basic.net

              我们看一下,下面例子:

              <div>This page rendered at @DateTime.Now</div>

             产生的html代码:

           <div>This page rendered at 12/7/1941 7:38:00 AM</div>

           Razor和我们熟悉的Web from 的方法的目的是一致的,那就是生成html代码。

           说到这里,我们不妨和Web Form做个比较:

           Web Form中的if/else语法:

          

<% if(User.IsAuthenticated) { %>
    <span>Hello, <%: User.Username %>!</span>
<% } %>
<% else { %>
    <span>Please <%: Html.ActionLink("log in") %></span>
<% } %>
          Razor中的实现:

@if(User.IsAuthenticated) {
    <span>Hello, @User.Username!</span>
} else {
    <span>Please @Html.ActionLink("log in")</span>
}

         Web Form中的for each循环:

<ul>
<% foreach( var auction in auctions) { %>
    <li><a href="<%: auction.Href %>"><%: auction.Title %></a></li>
<% } %>
</ul>

               Racor中的实现:

<ul>
@foreach( var auction in auctions) {
    <li><a href="@auction.Href">@auction.Title</a></li>
}
</ul>

                 虽然上面的情景用到了不同的语法,但是会产生相同的html代码。

           

          Differentiating Code and Markup

         Razor提供两种方法提供区别于标记:code nuggets和code blocks

         code nuggets

         code nuggets被渲染inline,而且可以混合文本,如下:          

Not Logged In: @Html.ActionLink("Login", "Login")
         Razor会认为关括号是语句的结束。上述语句会渲染如下输出:

Not Logged In: <a href="/Login">Login</a>

          注意:code nuggets必须要返回标记,如果code nuggets返回一个空值,那么当view执行的时候,会报错。

         

           Code blocks

           code block必须严格是代码,不能混合代码和标记。code block的代码要写在@{}的大括号里,而且要注意,必须要严格遵守当前的语法,比如说,每一句的结尾要有分号“;”          

@{
 LayoutPage = "~/Views/Shared/_Layout.cshtml";
 View.Title = "Auction " + Model.Title;
}
             code blocks不为view渲染任何东西,所以,你可以写任意的不需要返回值的代码。

             当然,code blocks 里定义的变量,是可以在code nuggets里使用的,但是,存在变量范围(作用域问题。)这很简单,我们来用下面的代码来说明:

@{
    // The title and bids variables are
    // available to the entire view
    var title = Model.Title;
    var bids = Model.Bids;
}
<h1>@title<h1>
<div class="items">
<!-- Loop through the objects in the bids variable -->
@foreach(var bid in bids) {
    <!-- The bid variable is only available within the foreach loop -->
    <div class="bid">
        <span class="bidder">@bid.Username</span>
        <span class="amount">@bid.Amount</span>
    </div>
}
<!-- This will throw an error: the bid variable does not exist at this scope! -->
<div>Last Bid Amount: @bid.Amount</div>
</div>

         Code Blocks不会渲染任何东西到view,相反code nuggets必须提供一个返回值来让view进行渲染,view会忽略Code Blocks的返回值。

           

           Layouts

           Razor通过Layouts来提供网站的统一风格,通过Layouts,一个view用来做模板,供其它的view来使用,从而定义全站的布局和风格。

          一个layout会包含主要的标记(scripts, CSS stylesheets, and structural HTML elements such as navigation and content containers)。接下,其它的view,只要指向这个Layouts就OK啦。

          

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>@ViewBag.Title - My ASP.NET MVC Application</title>
        <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
        <meta name="viewport" content="width=device-width" />
        @Styles.Render("~/Content/css")
        @Scripts.Render("~/bundles/modernizr")
    </head>
    <body>
        <header>
            <div class="content-wrapper">
                <div class="float-left">
                    <p class="site-title">@Html.ActionLink("your logo here", "Index", "Home")</p>
                </div>
                <div class="float-right">
                    <section id="login">
                        @Html.Partial("_LoginPartial")
                    </section>
                    <nav>
                        <ul id="menu">
                            <li>@Html.ActionLink("Home", "Index", "Home")</li>
                            <li>@Html.ActionLink("About", "About", "Home")</li>
                            <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                        </ul>
                    </nav>
                </div>
            </div>
        </header>
        <div id="body">
            @RenderSection("featured", required: false)
            <section class="content-wrapper main-content clear-fix">
                @RenderBody()
            </section>
        </div>
        <footer>
            <div class="content-wrapper">
                <div class="float-left">
                    <p>© @DateTime.Now.Year - My ASP.NET MVC Application</p>
                </div>
            </div>
        </footer>

        @Scripts.Render("~/bundles/jquery")
        @RenderSection("scripts", required: false)
    </body>
</html>
       

           引用Layout:

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

             view和Layout共同组成一个完整的页面。

       

           Partial Views

           可是,在更多的情况下,我们需要显示相同的内容在不同的view里。我们举个例子来说,比如说我们要制作的EBuy 拍卖网站,可能需要列出拍卖商品的细节——拍卖的标题、当前价格、商品缩略图。上面的信息,我们可能会在搜索页面用到,还会在列表页面用到。

           Asp.net mvc是通过partial views来实现这些功能的。partial views 是为渲染一个大的view的一部分而设计的。如下,是我们描述的上面的情况:

@model Ebuy.Auction

<div class="title">@Model.Title</div>
<div class="overview">
<p>
<strong>Current Price: </strong>
<span class="current-price">@Model.CurrentPrice.Code @Model.CurrentPrice.Value</span>
</p>
</div>
<h3>Description</h3>
<div class="description">
@Model.Description
</div>

          只需要把上面的代码保存为一个单独view文件就行,((e.g. /Views/Shared/Auction.cshtml))。接下来,可以用html.Partial(),来做为另一个view的一部分来渲染。

           如下:

@model Ebuy.Auction

<div class="title">@Model.Title</div>
<div class="overview">
<p>
<strong>Current Price: </strong>
<span class="current-price">@Model.CurrentPrice.Code @Model.CurrentPrice.Value</span>
</p>
</div>
<h3>Description</h3>
<div class="description">
@Model.Description
</div>

           下面是迭代一个auction 对象集合的例子:

@model IEnumerable<Auction>
<h2>Search Results</h2>
@foreach(var auction in Model) {
     @Html.Partial("Auction", auction)
}

          注意:第一个参数是指定的view的名称,第二个参数,指定partial view的model,就像controller方法的view()方法。第二个参数是可选的,如果没有指定,默认使用调用html.partial()view的model。比如上面的例子,如果没有指定第二个参数的话,ASP.NET MVC would pass the view’s Model property (of type IEnumerable<Auction>) in its place。

           Displaying Data

           我们已经很熟悉了,asp.net mvc的构架是通过view、model、controller来进行分离和区分的,它们协同工作来完成一个共同的目标。在处理中,controller扮演的角色是“交通警察”,它协同各部分组件,来执行程序的逻辑。在这个处理过程中,不可避免的,我们会用到各类数据来提供给用户。我们也清楚,显示信息不是controller的工作,是view来进行显示的。那么问题就来了,controller如果与view来进行信息通讯呢?

            asp.net mvc提供两种方式来为view-model-controller来进行通讯:ViewData和TempData。这两个对象是controller和view的字典属性。这样,controller传递信息给view只需要在controller里给变量进行赋值这么简单。

             以homeController为例

             

public ActionResult About()
{
    ViewData["Username"] = User.Identity.Username;
    ViewData["CompanyName"] = "EBuy: The ASP.NET MVC Demo Site";
    ViewData["CompanyDescription"] =
        "EBuy is the world leader in ASP.NET MVC demoing!";
    return View("About");
}
              然后,如果我们想在view中显示,只需要(About.cshtml):

<h1>@ViewData["CompanyName"]</h1>
<div>@ViewData["CompanyDescription"]</div>

              Cleaner access to ViewData values via ViewBag 

              asp.net mvc的controller和view在公开viewdata的同时也公开了一个类似的属性ViewBag。ViewBag属性是viewdata的一个简单包装,使viewdata字典作为一个动态的对象。

               例如,上面的例子,我们指向viewData字典的引用,可以通过ViewBag的动态属性来引用:

               public ActionResult About()
              {
                    ViewBag.Username = User.Identity.Username;
                    ViewBag.CompanyName = "EBuy: The ASP.NET MVC Demo Site";
                    ViewBag.CompanyDescription = "EBuy is the world leader in ASP.NET MVC demoing!";
                   return View("About");
              }
             and:
            <h1>@ViewBag.CompanyName</h1>
            <div>@ViewBag.CompanyDescription</div>

    

             View models

              viewData除了基本的字典行为外,还提供了一个model属性,model代表着请求的主要目标对象。虽然ViewData.Model属性和ViewData["model"]有概念上是一致的,但是model确实是ViewData不可或缺的重要成员,而且在请求中可能比其它的对象更重要。

               所以 们就有了如下代码:

public class CompanyInfo
{
    public string Name { get; set; }
    public string Description { get; set; }
}

                         
public ActionResult About()
{
    ViewBag.Username = User.Identity.Username;
    var company = new CompanyInfo {
        Name = "EBuy: The ASP.NET MVC Demo Site",
        Description = "EBuy is the world leader in ASP.NET MVC demoing!",
    };
    return View("About", company);
}
             About.cshtml

@{ var company = (CompanyInfo)ViewData.Model; }
<h1>@company.Name</h1>
<div>@company.Description</div>

             在这里我们可以着重看一下View()方法的重载。通过这个方法,view就可以获得company的实例引用,然后可以直接访问里面的属性。

       

             Strongly typed views

             默认情况下,Model属性在Razor语法里是动态,也就是说我们可以直接引用它的值,而不需要知道它的具体类型是什么。但是,为了方便在Razor view  在VS里的智能提示,我们最好指定我们使用的model的类型。

             代码很简单,如下:

@model CompanyInfo
<h1>@Model.Name</h1>
<div>@Model.Description</div>
             

             HTML and URL Helpers

             大部分的web请求的主要目的是发送html代码给用户,asp.net mvc以它的方式帮助我们产生html代码。除了Razor标记语言,asp.net mvc同样提供了帮助类用来简单高效产生html代码。最著名的两个就是HtmlHelper和UrlHelper类,公开在contorller和view的属性中。

             比如:

Here are some examples of the two helpers in action:
          <img src='@Url.Content("~/Content/images/header.jpg")' />
         @Html.ActionLink("Homepage", "Index", "Home")
The rendered markup looks like this:
          <img src='/vdir/Content/images/header.jpg' />
          <a href="/vdir/Home/Index">Homepage</a>


           在这里,我们需要记住的就是:HtmlHelper帮助我们产生html代码,UrlHelper帮助我们产生urls。当我们需要产生html和url的时候,想到这两个帮助类就好了。



              



发布了138 篇原创文章 · 获赞 11 · 访问量 40万+

猜你喜欢

转载自blog.csdn.net/yjjm1990/article/details/9008791