Orchard是如何呈现内容的
首先Orchard是一个建立在ASP.NET MVC框架上的CMS应用框架。Orchard在呈现内容的时候也遵循MVC的规律,也是通过Controller来处理Url请求并决定用那个View来呈现那种Model。不过这个Model就比较有讲究了,因为在Orchard中,一个页面上呈现的数据可能是多种多样的,有文章、有评论,有博客等等。而且这些数据都是可以通过后台设置任意组合的,也就是说我们不可能为每一个页面都创建一个类型的Model。那么在Orchard中是如何解决这一问题的呢?Orchard引入了形状(Shape)的概念,一个形状是一个动态类型的数据。引入形状的目的是为了取代原有静态的ASP.NET MVC视图的数据模型(Model),让数据模型的数据类型可以在运行时更改。这样就可以很好的解决Orchard需要处理多种不可预知的数据类型问题。
形状介绍(Introducing Shapes)
var shapeType = shapeName.Metadata.Type;
创建形状(Creating Shapes)
protected override DriverResult Display(
MapPart part, string displayType, dynamic shapeHelper)
{
return ContentShape("Parts_Map",
() => shapeHelper.Parts_Map(
Longitude: part.Longitude,
Latitude: part.Latitude));
}
using Maps.Models;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers; namespace Maps.Drivers
{
public class MapPartDriver : ContentPartDriver<MapPart>
{
protected override DriverResult Display(
MapPart part, string displayType, dynamic shapeHelper)
{
return ContentShape("Parts_Map",
() => shapeHelper.Parts_Map(
Longitude: part.Longitude,
Latitude: part.Latitude));
} //GET
protected override DriverResult Editor(
MapPart part, dynamic shapeHelper)
{
return ContentShape("Parts_Map_Edit",
() => shapeHelper.EditorTemplate(
TemplateName: "Parts/Map",
Model: part));
} //POST
protected override DriverResult Editor(
MapPart part, IUpdateModel updater, dynamic shapeHelper)
{
updater.TryUpdateModel(part, Prefix, null, null);
return Editor(part, shapeHelper);
}
}
}
标记了Get的Editor方法使用ContentShape去创建一个形状用于编辑模板。在这个案例中,形状类型名称是Parts_Map_Edit并且shapeHelper对象创建了一个EditorTemplate的形状。这是一个特殊的形状,它有一个模板名称属性和一个Model属性。模板名称属性指定了一个模板的部分路径,在这个案例中,“Parts/Map”将使Orchard在Views/EditorTemplates/Parts/Map.cshtml路径中查找相应的编辑模板。Model属性设置了这个模板所用到的数据。
命名形状和模板(Naming Shapes and Templates)
下表总结了形状类型和模板的命名规则:
| Applied To | Shape Naming Convention | Shape Type Example | Template Example |
|---|---|---|---|
| Content shapes | Content__[ContentType] | Content__BlogPost | Content-BlogPost |
| Content shapes | Content__[Id] | Content__42 | Content-42 |
| Content shapes | Content__[DisplayType] | Content__Summary | Content.Summary |
| Content shapes | Content_[DisplayType]__[ContentType] | Content_Summary__BlogPost | Content-BlogPost.Summary |
| Content shapes | Content_[DisplayType]__[Id] | Content_Summary__42 | Content-42.Summary |
| Content.Edit shapes | Content_Edit__[DisplayType] | Content_Edit__Page | Content-Page.Edit |
| Content Part templates | [ShapeType]__[Id] | Parts_Common_Metadata__42 | Parts/Common.Metadata-42 |
| Content Part templates | [ShapeType]__[ContentType] | Parts_Common_Metadata__BlogPost | Parts/Common.Metadata-BlogPost |
| Field templates | [ShapeType]__[FieldName] | Fields_Common_Text__Teaser | Fields/Common.Text-Teaser |
| Field templates | [ShapeType]__[PartName] | Fields_Common_Text__TeaserPart | Fileds/Common.Text-TeaserPart |
| Field templates | [ShapeType]__[ContentType]__[PartName] | Fields_Common_Text__Blog__TeaserPart | Fields/Common.Text-Blog-TeaserPart |
| Field templates | [ShapeType]__[PartName]__[FieldName] | Fields_Common_Text__TeaserPart__Teaser | Fields/Common.Text-TeaserPart-Teaser |
| Field templates | [ShapeType]__[ContentType]__[FieldName] | Fields_Common_Text__Blog__Teaser | Fields/Common.Text-Blog-Teaser |
| Field templates | [ShapeType]__[ContentType]__[PartName]__[FieldName] | Fields_Common_Text__Blog__TeaserPart__Teaser | Fields/Common.Text-Blog-TeaserPart-Teaser |
| LocalMenu | LocalMenu__[MenuName] | LocalMenu__main | LocalMenu-main |
| LocalMenuItem | LocalMenuItem__[MenuName] | LocalMenuItem__main | LocalMenuItem-main |
| Menu | Menu__[MenuName] | Menu__main | Menu-main |
| MenuItem | MenuItem__[MenuName] | MenuItem__main | MenuItem-main |
| Resource | Resource__[FileName] | Resource__flower.gif | Resource-flower.gif |
| Style | Style__[FileName] | Style__site.css | Style-site.css |
| Widget | Widget__[ContentType] | Widget__HtmlWidget | Widget-HtmlWidget |
| Widget | Widget__[ZoneName] | Widget__AsideSecond | Widget-AsideSecond |
| Zone | Zone__[ZoneName] | Zone__AsideSecond | Zone-AsideSecond |
- 内容项形状模板在 views/items目录下。
- 部件形状模板在views/parts目录下。
- 字段形状模板在views/fields目录下。
- 编辑模板在相应的 views/EditorTemplates/{相应模板名称} 目录下。例如:部件的编辑模板需要在 views/EditorTemplates/Parts目录下。
- 其他的形状模板都直接在views 目录下。
从模板文件名称到形状名称(From Template File Name to Shape Name)
- 将点(.)和反斜杠(\)改为下划线(_)。注意这点不包含后缀名中的点,如.cshtml。形状的模板文件需要在约定的目录中(见上文)。
- 短划线(-)改为双下划线(__)。
形状的可替换性呈现(Alternate Shape Rendering)
那一个可用替换将被呈现(Which Alternate Will Be Rendered?)
使用模板呈现形状(Built-In Content Item Alternates)
<img alt="Location" border="1" src="http://maps.google.com/maps/api/staticmap?
&zoom=14
&size=256x256
&maptype=satellite&markers=color:blue|@Model.Latitude,@Model.Longitude
&sensor=false" />
@model Maps.Models.MapPart <fieldset>
<legend>Map Fields</legend> <div class="editor-label">
@Html.LabelFor(model => model.Longitude)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.Latitude)
@Html.ValidationMessageFor(model => model.Latitude)
</div> <div class="editor-label">
@Html.LabelFor(model => model.Longitude)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.Longitude)
@Html.ValidationMessageFor(model => model.Longitude)
</div> </fieldset>
更多关于模板和Razor语法的信息,可查看《Template Files and their Locations》。
包装(Wrappers)
创建一个形状方法(Creating a Shape Method)
public class DateTimeShapes : IDependency {
private readonly IClock _clock;
public DateTimeShapes(IClock clock) {
_clock = clock;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
[Shape]
public IHtmlString DateTimeRelative(HtmlHelper Html, DateTime dateTimeUtc) {
var time = _clock.UtcNow - dateTimeUtc;
if (time.TotalDays > 7)
return Html.DateTime(dateTimeUtc, T("'on' MMM d yyyy 'at' h:mm tt"));
if (time.TotalHours > 24)
return T.Plural("1 day ago", "{0} days ago", time.Days);
if (time.TotalMinutes > 60)
return T.Plural("1 hour ago", "{0} hours ago", time.Hours);
if (time.TotalSeconds > 60)
return T.Plural("1 minute ago", "{0} minutes ago", time.Minutes);
if (time.TotalSeconds > 10)
return T.Plural("1 second ago", "{0} seconds ago", time.Seconds);
return T("a moment ago");
}
}
==========================================
作者:二十四画生
转载请注明来源于博客园——二十四画生的Blog,并保留有原文链接。
Orchard是如何呈现内容的的更多相关文章
- WPF界面设计技巧(5)—自定义列表项呈现内容
原文:WPF界面设计技巧(5)-自定义列表项呈现内容 接续上次的程序,稍微改动一下原有样式,并添加一个数据模板,我们就可以达成下面这样的显示功能: 鼠标悬停于文件列表项上,会在工具提示中显示图像缩略图 ...
- 第二篇:呈现内容_第二节:WebControl呈现
一.WebControl的呈现过程 WebControl派生自Control类,所以WebControl的呈现功能基于Control的呈现逻辑之上,但有了比较大的扩展. 首先,WebControl重写 ...
- 第二篇:呈现内容_第一节:Control呈现
一.Control的呈现过程 在上个章节““生死有序”的控件生命周期”中,我们提到Render是控件开发的主角,但在控件树的“合成模式(Composite)”部分这位主角却缺席了(戏份太多的缘由).哦 ...
- Orchard运用 - 定制呈现最新博客文章
每个博客系统为了吸引更多访问量,一般都会在首页或侧边栏列举一些最新文章/随笔以获取更多点击.其实也就是查询出最新的几篇文章并按照简练的方式呈现,比如一般都只有标题及其对应的链接,有时也会标注一下作者和 ...
- 第二篇:呈现内容_第三节:CompositeControl呈现
一.CompositeControl的呈现过程 CompositeControl派生自WebControls,重写了Render(HtmlTextWriter writer)方法.在调用基类WebCo ...
- Orchard学习资料,适合入门上手
名词解释: http://www.cnblogs.com/esshs/archive/2011/06/01/2067501.html Orchard如何工作: http://www.cnblogs ...
- [翻译]Orchard如何工作
Orchard一直是博主心中神一般的存在,由于水平比较菜,Orchard代码又比较复杂看了几次都不了了之了.这次下定决心要搞懂其工作原理,争取可以在自己的项目中有所应用.为了入门先到官网去学习一下相关 ...
- Orchard 微软CMS项目介绍
我之前的项目中使用了Orchard, 它依据依赖注入的思想而做的模块化让我深深为之着迷,这里开始宣传一下这个架构. 包含的概念非常之多,我现在也不甚了解.Orchard就是自己想控制它改变它的话需要非 ...
- Orchard官方文档翻译(十一) 使用Tags组织文本
原文地址:http://docs.orchardproject.net/Documentation/Organizing-content-with-tags 想要查看文档目录请用力点击这里 最近想要学 ...
随机推荐
- [qemu][kvm] 在kvm嵌套kvm的虚拟机里启动kvm加速
常规情况下,如果在kvm的虚拟机里,又想使用kvm的虚拟机,会报如下的错误信息: [root@host0 nlb]# Could not access KVM kernel module: No su ...
- IE浏览器Web自动化
一.常见问题 1.1 在IE11浏览器下运行自动化脚本特别缓慢. 具体表现:(64位IE驱动器下)脚本运行慢,尤其是文本框输入,其它浏览器是一起输入,但IE是单个字节输入字符串 解决方法:更换IE的 ...
- VB调用C# dll
cd C:\Windows\Microsoft.NET\Framework\v4.0.30319注册regasm myTest.dll /tlb:myTest.tlb
- caffe中的卷积
https://www.zhihu.com/question/28385679 如上,将三维的操作转换到二维上面去做,然后调用GEMM库进行矩阵间的运算得到最后结果. 两个矩阵相乘,需要中间的那个维度 ...
- Django进阶之QuerySet和中介模型
QuerySet QuerySet是查询集,就是传到服务器上的url里面的查询内容.其形态类似于Python的列表,列表中的元素是QuerySet对象.支持大部分列表的内置方法. 可切片 QueryS ...
- [js]js代码执行顺序/全局&私有变量/作用域链/闭包
js代码执行顺序/全局&私有变量/作用域链 <script> /* 浏览器提供全局作用域(js执行环境)(栈内存) --> 1,预解释(仅带var的可以): 声明+定义 1. ...
- 69A
#include <stdio.h> int main() { int n; int sum1=0, sum2=0, sum3=0; int x, y, z; scanf("%d ...
- MySQL AUTO_INCREMENT 学习总结
之前有碰到过开发同事指出一张InnoDB表的自增列 AUTO_INCREMENT 值莫明的变大,由于这张表是通过mysqldump导出导入的. 问题排查: 1.首先,查看表表义的sql部分的 auto ...
- ueditor富文本上传图片的时候报错"未找上传数据"
最近因为需求所以在ssh项目中使用了Ueditor富文本插件,但是在上传图片的时候总是提示“未找到上传数据”,之后百度了好久终于弄明白了.因为Ueditor在上传图片的时候会访问controller. ...
- IRC 打字交流
kali 里面用 apt-get install weechat 安装完成后,输入 weechat 命令就能启动客户端了 要想使用 IRC,就需要先连接一个 irc 服务器,选择了大名鼎鼎的 chat ...