Slide 1

Slide 1 text

Orchard MODULES GROWING YOUR

Slide 2

Slide 2 text

We wanted a modern CMS based on ASP.NET MVC. We also wanted an extremely extensible platform similar to what PHP has with Drupal. But most importantly we wanted to build better bridges between our team at Microsoft and the open-source community. “ ” Betrand Le Roy, Creator of Orchard

Slide 3

Slide 3 text

Content FUNDAMENTALS

Slide 4

Slide 4 text

ContentFields

Slide 5

Slide 5 text

ContentFields contain Data “Get in my belly!” “Oh noes!”

Slide 6

Slide 6 text

ContentParts

Slide 7

Slide 7 text

ContentParts have Behavior scary eye big sharp teeth really mean!

Slide 8

Slide 8 text

ContentTypes

Slide 9

Slide 9 text

ContentTypes are Consumable by Users

Slide 10

Slide 10 text

Types Parts Fields Data

Slide 11

Slide 11 text

Types Fields Data

Slide 12

Slide 12 text

content item a is an each instance of content type

Slide 13

Slide 13 text

Module/Feature

Slide 14

Slide 14 text

Module/Feature features extend the CMS modules contain and distribute

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

Module FUNDAMENTALS

Slide 17

Slide 17 text

RecordsAndParts records are Data Models parts are View Models

Slide 18

Slide 18 text

HandlersAndDrivers handlers give behavior to the code drivers are are specialized controllers

Slide 19

Slide 19 text

ShapeTemplates

Slide 20

Slide 20 text

DependencyInjection

Slide 21

Slide 21 text

Controllers

Slide 22

Slide 22 text

ModuleManifest

Slide 23

Slide 23 text

A manifest stores metadata that Orchard uses to describe modules and themes to the system, such as name, version, description, author, and tags.” Manifest [Module|Theme] “ docs.orchardproject.net

Slide 24

Slide 24 text

Name: AntiSpam AntiForgery: enabled Author: The Orchard Team Website: http://orchardproject.net Version: 1.7.2 OrchardVersion: 1.7.2 Description: Provides anti-spam services to protect your Features: Orchard.AntiSpam: Name: Anti-Spam Description: Provides anti-spam services to prot Category: Security Dependencies: Orchard.Tokens, Orchard.jQuery Akismet.Filter: Name: Akismet Anti-Spam Filter Description: Provides an anti-spam filter based Category: Security Dependencies: Orchard.AntiSpam 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

Slide 25

Slide 25 text

Orchard EXECUTABLE

Slide 26

Slide 26 text

WebSiteAndConsoleApp

Slide 27

Slide 27 text

The Orchard command interpreter supports running a few built-in commands as well as specific commands from enabled features of an Orchard installation. “ ” Orchard.exe

Slide 28

Slide 28 text

C:\Orchard\src\Orchard.Web\bin> Orchard.exe_

Slide 29

Slide 29 text

C:\Orchard\src\Orchard.Web\bin> Orchard.exe Initializing Orchard session. (This might take a few seconds...) Type "?" for help, "exit" to exit, "cls" to clear screen orchard> _

Slide 30

Slide 30 text

orchard> call me "Rock God" Error executing command "call me Rock God" ---------------------------------------------------------- No command found matching arguments "call me Rock God". Commands available: site setting set baseurl, autoroute create, theme list, theme activate, widget create, layer create, menuitem create, menu create, blog create, blog import, ...

Slide 31

Slide 31 text

Module DEVELOPMENT

Slide 32

Slide 32 text

Step #1 Code Generation

Slide 33

Slide 33 text

CodeGeneration

Slide 34

Slide 34 text

orchard> feature enable Orchard.CodeGeneration_

Slide 35

Slide 35 text

orchard> feature enable Orchard.CodeGeneration Enabling features Orchard.CodeGeneration Code Generation was enabled orchard> _

Slide 36

Slide 36 text

orchard> feature enable Orchard.CodeGeneration Enabling features Orchard.CodeGeneration Code Generation was enabled orchard> codegen module SlideShare /IncludeInSolution:true_

Slide 37

Slide 37 text

orchard> feature enable Orchard.CodeGeneration Enabling features Orchard.CodeGeneration Code Generation was enabled orchard> codegen module SlideShare /IncludeInSolution:true Creating Module SlideShare Module SlideShare created successfully orchard> _

Slide 38

Slide 38 text

ReadyGo

Slide 39

Slide 39 text

UpdateManifest

Slide 40

Slide 40 text

Name: SlideShare AntiForgery: enabled Author: Jay Harris, Arana Software Website: http://www.aranasoft.com Version: 1.0 OrchardVersion: 1.0 Description: Provide SlideShare presentations as an atta Features: SlideShare: Description: Provide SlideShare presentations as an Category: Social 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

Slide 41

Slide 41 text

Step #2 Records & Parts

Slide 42

Slide 42 text

RecordsAndParts AddNewClass

Slide 43

Slide 43 text

namespace SlideShare.Models { public class SlideShareRecord { } } 1 2 3 4 5 6 7 8 9 10

Slide 44

Slide 44 text

using Orchard.ContentManagement.Records; namespace SlideShare.Models { public class SlideShareRecord : ContentPartRecord { } } 1 2 3 4 5 6 7 8 9 10

Slide 45

Slide 45 text

using Orchard.ContentManagement.Records; namespace SlideShare.Models { public class SlideShareRecord : ContentPartRecord { public virtual string SlideShareId { get; set; } public virtual int? StartFromSlide { get; set; } } } 1 2 3 4 5 6 7 8 9 10

Slide 46

Slide 46 text

Use Namespace MODELS or RECORDS

Slide 47

Slide 47 text

Mark Properties VIRTUAL

Slide 48

Slide 48 text

Mind Your BASE CLASS

Slide 49

Slide 49 text

using Orchard.ContentManagement.Records; namespace SlideShare.Models { public class SlideShareRecord : ContentPartRecord { public virtual string SlideShareId { get; set; } public virtual int? StartFromSlide { get; set; } } } 1 2 3 4 5 6 7 8 9 10

Slide 50

Slide 50 text

using Orchard.ContentManagement; using Orchard.ContentManagement.Records; namespace SlideShare.Models { public class SlideShareRecord : ContentPartRecord { public virtual string SlideShareId { get; set; } public virtual int? StartFromSlide { get; set; } } public class SlideSharePart : ContentPart { } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

Slide 51

Slide 51 text

public class SlideSharePart : ContentPart { public string SlideShareId { get { return Record.SlideShareId; } set { Record.SlideShareId = value; } } [Range(1, 20)] public int? StartFromSlide { get { return Record.StartFromSlide; } set { Record.StartFromSlide = value; } } } 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

Slide 52

Slide 52 text

Compile Before Proceeding

Slide 53

Slide 53 text

Step #3 Data Migration

Slide 54

Slide 54 text

orchard> codegen datamigration SlideShare_

Slide 55

Slide 55 text

orchard> codegen datamigration SlideShare Creating Data Migration for SlideShare Data migration created successfully in Module SlideShare orchard> _

Slide 56

Slide 56 text

DataMigration

Slide 57

Slide 57 text

using System.Data; using Orchard.Data.Migration; namespace SlideShare { public class Migrations : DataMigrationImpl { public int Create() { // Creating table SlideShareRecord SchemaBuilder.CreateTable("SlideShareRecord", table => table !!!! .ContentPartRecord() !!!! .Column("SlideShareId", DbType.String) !!!! .Column("StartFromSlide", DbType.Int32) ); return 1; } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

Slide 58

Slide 58 text

// column methods can use generic types... !!!! .Column("SlideShareId") !!!! .Column("StartFromSlide") // or they can use a DbType argument. !!!! .Column("SlideShareId", DbType.String) !!!! .Column("StartFromSlide", DbType.Int32) // either way. just not both. 11 12 13 11 12 13

Slide 59

Slide 59 text

public class Migrations : DataMigrationImpl { public int Create() { // The ‘return’ is for versioning return 1; } public int UpdateFrom1() { // Do some data migrations return 2; } public int UpdateFrom2() { // More data migrations return 3; } } 5 6 14 15 16 25 26 27 33 34 35

Slide 60

Slide 60 text

Indicates if administrators can attach the Content Part to any Content Type, or if the Part is limited only to Types explicitly specified by the Module. ” Attachable [Content Part] “

Slide 61

Slide 61 text

using System.Data; using Orchard.ContentManagement.MetaData; using Orchard.Core.Contents.Extensions; using Orchard.Data.Migration; using SlideShare.Models; namespace SlideShare { public class Migrations : DataMigrationImpl { public int UpdateFrom1() { ContentDefinitionManager.AlterPartDefinition( "SlideSharePart", cfg => cfg.Attachable()); return 2; } } } 1 2 3 4 5 6 7 8 17 18 19 20 21 22 23 24

Slide 62

Slide 62 text

using System.Data; using Orchard.ContentManagement.MetaData; using Orchard.Core.Contents.Extensions; using Orchard.Data.Migration; using SlideShare.Models; namespace SlideShare { public class Migrations : DataMigrationImpl { public int UpdateFrom1() { ContentDefinitionManager.AlterPartDefinition( typeof(SlideSharePart).Name, cfg => cfg.Attachable( return 2; } } } 1 2 3 4 5 6 7 8 17 18 19 20 21 22 23 24

Slide 63

Slide 63 text

Step #4 Handlers & Drivers

Slide 64

Slide 64 text

CreateHandler

Slide 65

Slide 65 text

Most Handlers will be very simple behavior managers. Often, the only behavior they will have to specify is how data is to be stored.” Part Handlers “

Slide 66

Slide 66 text

using SlideShare.Models; using Orchard.ContentManagement.Handlers; using Orchard.Data; namespace SlideShare.Handlers { public class SlideShareHandler : ContentHandler { public SlideShareHandler( IRepository repository) { Filters.Add(StorageFilter.For(repository)); } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

Slide 67

Slide 67 text

CreateDriver

Slide 68

Slide 68 text

using System; using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; using SlideShare.Models; namespace SlideShare.Drivers { public class SlideShareDriver : ContentPartDriver { } } 1 2 3 4 5 6 7 8 9 10 11 12 13

Slide 69

Slide 69 text

protected override DriverResult Display( SlideSharePart part, string displayType, dynamic shapeHelper) { return ContentShape("Parts_SlideShare", () => shapeHelper.Parts_SlideShare( SlideShareId: part.SlideShareId, StartFromSlide: part.StartFromSlide ) ); } 10 11 12 13 14 15 16 17 18 19 20 21

Slide 70

Slide 70 text

//GET protected override DriverResult Editor( SlideSharePart part, dynamic shapeHelper) { return ContentShape("Parts_SlideShare_Edit", () => shapeHelper.EditorTemplate( TemplateName: "Parts/SlideShare", Model: part, Prefix: Prefix ) ); } 23 24 25 26 27 28 29 30 31 32 33 34 35

Slide 71

Slide 71 text

//POST protected override DriverResult Editor( SlideSharePart part, IUpdateModel updater, dynamic shapeHelper) { updater.TryUpdateModel(part, Prefix, null, null); return Editor(part, shapeHelper); } 37 38 39 40 41 42 43 44 45

Slide 72

Slide 72 text

Step #5 Shape Templates

Slide 73

Slide 73 text

DisplayTemplate

Slide 74

Slide 74 text

Mind Your VIEW PATHS

Slide 75

Slide 75 text

protected override DriverResult Display( SlideSharePart part, string displayType, dynamic shapeHelper) { return ContentShape("Parts_SlideShare", () => shapeHelper.Parts_SlideShare( SlideShareId: part.SlideShareId, StartFromSlide: part.StartFromSlide ) ); } 10 11 12 13 14 15 16 17 18 19 20 21

Slide 76

Slide 76 text

“Parts_SlideShare” Views/Parts/SlideShare.cshtml translates to

Slide 77

Slide 77 text

1 2 3 4 5 6 7 8 9 10

Slide 78

Slide 78 text

@if(!string.IsNullOrWhiteSpace(Model.SlideShareId as string)) { } 1 2 3 4 5 6 7 8 9

Slide 79

Slide 79 text

@if(!string.IsNullOrWhiteSpace(Model.SlideShareId as string)) { var startSlide = Model.StartFromSlide as int?; var startSlideQS = startSlide.HasValue ? string.Format("startSlide={0}", startSlide.Value) : string.Empty; var slideShareUrl = string.Format( "http://www.slideshare.net/slideshow/embed_code/ {0}?{1}", Model.SlideShareId, startSlideQS);

Slide 80

Slide 80 text

EditorTemplate

Slide 81

Slide 81 text

//GET protected override DriverResult Editor( SlideSharePart part, dynamic shapeHelper) { return ContentShape("Parts_SlideShare_Edit", () => shapeHelper.EditorTemplate( TemplateName: "Parts/SlideShare", Model: part, Prefix: Prefix ) ); } 23 24 25 26 27 28 29 30 31 32 33 34 35

Slide 82

Slide 82 text

“Parts/SlideShare” Views/EditorTemplates/ Parts/SlideShare.cshtml translates to

Slide 83

Slide 83 text

@model SlideShare.Models.SlideSharePart SlideShare Fields
@Html.LabelFor(m => m.SlideShareId)
@Html.TextBoxFor(m => m.SlideShareId) @Html.ValidationMessageFor(m => m.SlideShareId)
1 2 3 4 5 6 7 8 9 10 11

Slide 84

Slide 84 text

@model SlideShare.Models.SlideSharePart SlideShare Fields
@Html.LabelFor(m => m.SlideShareId)
@Html.TextBoxFor(m => m.SlideShareId) @Html.ValidationMessageFor(m => m.SlideShareId)
@Html.LabelFor(m => m.StartFromSlide)
@Html.TextBoxFor(m => m.StartFromSlide) @Html.ValidationMessageFor(m => m.StartFromSlide)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

Slide 85

Slide 85 text

ShapePlacement

Slide 86

Slide 86 text

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

Slide 87

Slide 87 text

Celebrate

Slide 88

Slide 88 text

EnableFeature

Slide 89

Slide 89 text

AddContentDone

Slide 90

Slide 90 text

Module DISTRIBUTION

Slide 91

Slide 91 text

OrchardPackaging

Slide 92

Slide 92 text

orchard> feature enable Orchard.Packaging Enabling features Orchard.Packaging Packaging was enabled orchard> _

Slide 93

Slide 93 text

orchard> feature enable Orchard.Packaging Enabling features Orchard.Packaging Packaging was enabled orchard> package create SlideShare C:\Code_

Slide 94

Slide 94 text

orchard> feature enable Orchard.Packaging Enabling features Orchard.Packaging Packaging was enabled orchard> package create SlideShare C:\Code Package "C:\Code\Orchard.Module.SlideShare.1.0.nupkg" successfully created orchard> _

Slide 95

Slide 95 text

...you’ll be able to achieve all kinds of glory and fame. “ ” orchardproject.net

Slide 96

Slide 96 text

No content

Slide 97

Slide 97 text

No content

Slide 98

Slide 98 text

No content

Slide 99

Slide 99 text

No content

Slide 100

Slide 100 text

No content

Slide 101

Slide 101 text

No content

Slide 102

Slide 102 text

Profit

Slide 103

Slide 103 text

github.com/aranasoft

Slide 104

Slide 104 text

bit.ly/growingOrchard

Slide 105

Slide 105 text

...you’ll be able to achieve all kinds of glory and fame. “ ” orchardproject.net

Slide 106

Slide 106 text

jay harris P R E S I D E N T [email protected] #growingOrchard @jayharris

Slide 107

Slide 107 text

Thanks