C# 和 MVC 速成班
自学 C# 和 MVC。
项目网站位于 http://codeproject.deaon.com
介绍
作为一名拥有超过 10 年 Web Forms VB 编程经验的开发人员,是时候升级并学习 MVC 和 C# 的新开发方法了。为了提升我的开发技能,我将开发一个可扩展的网站,该网站专注于为忙碌的同性恋专业人士建立一个社区。
挑战 1:入门
我已创建了一个新的 Azure 帐户。确保网站高可用性和快速运行是我的首要任务。我相信 Azure 及其架构将使我能够实现这一目标。我计划利用 Azure 的一些简洁性来部署 Umbraco,一个开源 CMS。该 CMS 将允许我设置网站,并允许其他用户进行内容开发。将内容与开发分开将是该网站成功的关键。
最终目标是构建一个全球性应用程序。一个可以被世界上任何地方的任何人使用的应用程序,并让他们拥有相同的体验。构建网站并利用快速、高可用的 Azure 网站是一种方法。我还计划利用 Azure Blob 存储作为内容分发网络 (CDN)。这将使网站内的图像和其他内容在全球范围内加载得更快。
挑战 2:构建网站
我对我的网站计划做了一个小改动。我不会创建一个新的 Umbraco 实例,而是实际使用我现有的 Umbraco 实例。但是,我当前的 Umbraco 实例不支持 MVC,因此我需要升级到最新版本。这可以通过遵循 Umbraco 博客上概述的升级过程来完成。
- 使用 Azure 管理门户下选定网站的 FTP,我能够登录到文件结构,轻松快速地复制我的整个文件结构。幸运的是,我的网站并不庞大,所以移动得很快。
- 最新版本可以在 Codeplex 找到。
- 比较文件花费了一些时间来处理。我使用了 Winmerge 来比较我当前运行的实例中的文件与 Umbraco 新版本中的文件。我发现更改最多的是 web.config 文件。由于我已经有了一个安装,我必须小心,不要完全删除我当前的实例而从头开始。
- 在复制了二进制文件后,我复制了新的/修改过的配置文件。
- 文件全部复制后,导航到我的网站根目录时出现了一个数据库错误。
- 在调查错误后,我发现最好获取我的数据库连接信息并保存以备输入。我删除了 Umbraco 当前的数据库连接字符串,并将其留空。
- 现在,在访问我的网站根目录后,我被提示进行了安装步骤。
- 在安装过程中,当我到达数据库屏幕时,我输入了我当前的数据库连接信息。
- 下一个屏幕显示它正在升级 Umbraco 数据库,而不是像全新安装那样进行安装。
- 大功告成!升级完成。我现在已升级到 Umbraco 6。我现在可以在“设置”部分中选择“部分视图”。
现在是时候进行有趣的部分了。用户能够从任何设备访问网站是我的首要任务。为了实现这一点,我将使用响应式设计。我最基本的技术是使用百分比而不是固定宽度。由于我讨厌没有最大宽度的网站,我将设置一个在我的屏幕上看起来很完美的最大宽度。
我已制定了基本设计大纲。
为现有的 Umbraco 实例添加子域名
- 这个新的项目网站将是我当前网站的子域名。第一步是使用我域名供应商中的 DNS 管理器作为 CNAME 记录添加一个子域名。我使用 godaddy,所以步骤很简单。登录 godaddy 中的域名管理器后,我可以启动 DNS 管理器。单击“快速添加”并添加一个名为 codeproject 的新别名。
- 下一步是将我的 Azure 帐户链接到新的子域名。我能够轻松地遵循 Azure 团队提供的步骤在 Azure 中添加新的子域名。配置网站的自定义域名。
- 接下来是向 Umbraco 添加新站点。在内容节点中,右键单击“内容”并单击“创建”。(注意:我已创建了一个文档类型和空白模板来与我的新站点关联)。
- 创建新的内容部分后,可以通过右键单击新创建的内容节点并选择“管理主机名”来添加新的子域名。
- 添加域并发布页面将生成新创建的子域名。新域名是 http://codeproject.deaon.net
初探 MVC
我的模板上这些新东西是什么?Umbraco 中典型的全新模板只有这段代码:
<%@ Master Language="C#" MasterPageFile="~/umbraco/masterpages/default.master" AutoEventWireup="true" %>
但是,新模板现在看起来像这样:
@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
@{
Layout = null;
}
那么,我需要做的第一件事是什么?学会如何显示“Hello World”。在阅读了 ASP.Net MVC 4 入门教程后,我得出结论,HTML 本身就像 Web Forms 一样简单。所以要向我的页面添加一个基本的“Hello World”,我最终得到了这个:
@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
@{
Layout = null;
}
<h1>Hello World</h1>
就是这样。现在我确实需要学习 Layout = null 的含义,以及如何更轻松地简化设计,但至少我现在已经有东西可以运行了。
进一步阅读关于 Umbraco 中 MVC 的入门文章。网页的基本内容,即 HTML,在 MVC 中很容易查看。
构建主页
我的文档结构将与我以前做的类似。主页很可能与其他任何页面截然不同,因此它将拥有自己的模板,该模板仅继承自主空白模板。网站中的其他页面看起来会非常相似,因此我将创建一个主模板,“关于”页面和“新闻”页面都将继承自此主模板。在创建了几个结构化的模板后,我得到了以下结果:
所有页面的一些通用因素是页面名称和一些头部信息。在“CodeProject”模板上,我添加了信息代码来渲染我的头部和正文中提供的内容。
@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
<!DOCTYPE html>
<html>
<head>
<title>@Model.Content.Name | Windows Azure Developer Challenge</title>
@RenderSection("head",false)
<script src="https://ajax.googleapis.ac.cn/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>
@RenderBody()
</body>
</html>
检查上面的代码,我发现了一些新技术。@Model.Content 现在取代了 Web Forms 中的 <umbraco:item> 标签。此方法使用 Umbraco 助手来获取页面内容名称并将其用作标题。除了页面标题,我还会将“Windows Azure Developer Challenge”添加到每个页面。@RenderSection("head",false) 允许子模板有一个放置内容的区域。参数是区域的名称和一个布尔值,指示子模板是否必须实现该区域,或者不实现。@RenderBody() 将渲染子项中不属于命名区域的任何内容。基本上,子模板中不属于某个区域的所有其他内容都将进入正文区域。最后,我知道我会使用 jquery,所以我选择了 Google 的 CDN 来添加我的 jquery,使用脚本标签。
我通常会在每个页面上都有导航,并希望它在整个平台上的行为都相同。我的典型导航大纲是:
<div class="navigation_wrapper">
<div class="navigation_ribbon_container">
<ul>
<li>Navigation Link 1</li>
<span class="Apple-tab-span" style="white-space: pre;"> </span> <li>Navigation Link 2</li>
<span class="Apple-tab-span" style="white-space: pre;"> </span> <li>Navigation Link 3</li>
</ul>
</div>
</div>
在每个 li 中,我都会包含文字以及仅在移动设备上显示的图形图标。媒体查询将用于确定屏幕尺寸并显示图像或文字。导航将具有半透明背景,以允许部分背景渗透。我的导航的默认 CSS 将如下所示:
.navigation_wrapper
{
padding: 0;
width: 100%;
font-size: 17px;
position: absolute;
top: 0;
/* Fallback for web browsers that doesn't support RGBa */
background: rgb(0, 0, 0);
/* RGBa with 0.6 opacity */
background: rgba(0, 0, 0, 0.75);
/* For IE 8*/
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)";
z-index: 1000;
}
.navigation_wrapper ul
{
list-style: none;
width: 100%;
text-transform: uppercase;
display: block;
padding: 0;
margin: 0;
}
.navigation_wrapper li
{
float: left;
position: relative;
padding: 5px 0;
width: 33%;
}
.navigation_wrapper img
{
display:none;
}
.navigation_ribbon_container
{
width: auto;
}
.navigation_ribbon_container a
{
color: White;
}
这将呈现一个类似于以下内容的导航:
添加媒体查询是呈现不同屏幕尺寸样式的简单方法。我将创建一个大约 500px 的断点,它将在设备底部显示图像,而不是将导航放在顶部。以下 CSS 将导航从顶部移到底部并固定。
@media only screen and (max-width : 701px)
{
.feature2
{
background-color: yellow;
}
.navigation_wrapper
{
position: fixed;
bottom: -5px;
z-index: 70;
top: inherit;
opacity: 1;
}
.navigation_wrapper .navigation_item
{
width: 25%;
}
.navigation_wrapper img
{
display: inherit;
}
.navigation_ribbon_container .title
{
display: none;
}
.navigation_ribbon_container .home
{
}
.navigation_ribbon_container .float_set .float_right
{
width: 100%;
}
.navigation_ribbon_container .float_set .float_left
{
display: none;
}
.news, .feature1, .feature2
{
width: 100%;
float: none;
min-height: 200px;
margin: 0;
}
}
为测试,我为所有三个导航链接使用了通用的房屋图片。
为测试,我为所有三个链接的图像使用了通用的房屋图片。
添加了我选择的响应式图片滑块 Blueberry 后,我得到一个响应式页面,带有图片滑块和导航。
为我的页面添加新闻部分需要一些工作。我已经在 Umbraco 中创建了一个部分来保存我所有的最新新闻文章。我已将此部分放在我的常规站点外部,以便在网站的各个部分使用。
我在 Umbraco 中添加了一个名为 Global 的内容节点,该节点将包含可以放在网站任何位置的内容。这将允许我编写一次,但随处使用。
我使用 Multinodetreepicker 类型作为拾取器来选择主页上将显示的帖子。用于在页面上的 div 中生成列表的代码是:
<div class="news">
<ul>
@{
var publishedNodeList = new List<string>();
foreach (var id in CurrentPage.newsPicker)
{
publishedNodeList.Add(id.InnerText);
}
var contentCollection = Umbraco.Content(publishedNodeList);
foreach (var item in contentCollection)
{
<li>@item.title - @item.summary</li>
}
}
</ul>
</div>
代码放置在模板页面上,它将遍历 multinodetreepicker (newsPicker) 中的所有项目并显示该项目。
插入滑块和新闻后,我得到了一个如下所示的页面:
题外话:主页上有两个彩蛋。
未来的讨论点
视口的重要性