Friday, August 27, 2010

Adding a new Module Using VS 2010

Adding a new Module in Orchard 


Follow These Steps:




0.1.  To begin, enable the Scaffolding feature in Orchard from the "Features" admin panel area.





1. Right-click the Modules node in VS Solution Explorer, and choose “Add > New Project…”


2. In the project creation screen, choose “ASP.NET MVC 2.0 Empty Web Application
 On the path text box, it is default to \src folder. Change it to \src\Orchard.Web\Modules\ folder (Screenshot below). Else Orchard will not recognize the new module.
Finally Type “Tour” for the area name and click [OK].



3. For Orchard to discover this module, you need to add a module.txt file at the project root folder and insert the following content.









name: Tour
antiforgery: enabled
author: The Orchard Team
website: http://Orchard.net
version: 1.0.0
orchardversion: 1.0.0
description:  Add Hotel Details.
features:
    Tour:
        Description: A simple product part.
        Category: Travel

4. Check (Not necessary)
Type Ctrl-F5 to build and run in VS.
Login as admin (using the admin account you created during setup) and navigate to the admin page


Scroll down to look for Site Configuration menu and click on Features

If you had done everything right, you will see Tour  as a module under the Commerce Travel.


5. Add Orchard.Framework and Orchard.Themes to the project reference


6. To begin with, we need a class to contain the data for the part. Data classes are conventionally added to the "Models" folder of the project. Right-click the Models folder in Visual Studio and choose "Add > Class" from the context menu. With name TourPart.cs
With code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using System.ComponentModel.DataAnnotations;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Records;

namespace Tour.Models
{
    public class TourRecord : ContentPartRecord
    {
        public virtual string TourCode { get; set; }
        public virtual string Description { get; set; }

    }
    public class TourPart : ContentPart<TourRecord>
    {
        [Required]
        public string TourCode
        {
            get { return Record.TourCode; }
            set { Record.TourCode = value; }
        }

        [Required]
        public string Description
        {
            get { return Record.Description; }
            set { Record.Description = value; }
        }
    }
}

Now build the Tour project to ensure your Record class compiles successfully.

7. We are going to create a data migration for our Tour module. Why do we need a migration class? The reason is that defining a Record and Part class to store the data doesn't actually impact the database in any way. A data migration is what tells Orchard how to update the database schema when the Tour feature is enabled (the migration runs when the feature is activated). A migration can also upgrade the database schema from prior versions of a module to the schema required by a newer version of a module - this is an advanced topic that won't be covered in this tutorial.
Add DataMigrations folder in root of Tour.
DataMigrations>>TourDataMigrations.cs
Add this Code:
using System.Collections.Generic;
using System.Data;
using Orchard.Data.Migration;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.Core.Contents.Extensions;
using Orchard.Indexing;
using Tour.Models;

namespace Tour.DataMigrations
{
    public class TourDataMigration : DataMigrationImpl
    {

        public int Create()
        {
            // Creating table TourRecord
            SchemaBuilder.CreateTable("TourRecord", table => table
                .ContentPartRecord()
                .Column("TourCode", DbType.String)
                .Column("Description", DbType.String)
            );

            return 1;
        }

    }
}


8. Now let's add the handler for the Tour part. A handler in Orchard is a class that defines the behavior of the part, handling events or manipulating data model prior to rendering the part. The Tour part is very simple, and in this case, our handler class will only specify that an IRepository of TourRecord should be used as the storage for this part.

Create folder Handlers in roote of Tour
Handlers>> TourHandler.cs
Insert code as :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Orchard.ContentManagement.Handlers;
using Tour.Models;
using Orchard.Data;

namespace Tour.Handlers
{
    public class TourHandler : ContentHandler
    {
        public TourHandler(IRepository<TourRecord> repository)
        {
            Filters.Add(StorageFilter.For(repository));
        }
    }
}


9. We will also add a driver for our Tour part. A driver in Orchard is a class that defines associations of templates (or views) to display for each context in which the Tour part can render. For example, when displaying a Tour on the front-end, a "Display" method defines the name of the template to use for different display Types (for example, "details" or summary"). Similarly, an "Editor" method of the driver defines the template to use for displaying the editor of the Tour part (for entering values of the TourCode and Description
 Fields). We are going to keep this part simple and just use " Tour  " as the name of the template to use for both Display 
And Editor Contexts (and all displayTypes). Add the TourDriver class as follows.
Create folder Drivers in roote of Tour
Drivers >> TourDriver.cs
Insert code as :


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Tour.Models;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement;
using Orchard.Core.ContentsLocation.Models;

namespace Tour.Drivers
{
    public class TourDriver : ContentItemDriver<TourPart>
    {
        protected override DriverResult Display(TourPart part, string displayType)
        {
            return ContentPartTemplate(part, "Tour")
                   .Location(part.GetLocation(displayType));
        }

        //GET
        protected override DriverResult Editor(TourPart part)
        {
            return ContentPartTemplate(part, "Tour")
                   .Location(part.GetLocation("Editor"));
        }

        //POST
        protected override DriverResult Editor(TourPart part, IUpdateModel updater)
        {
            updater.TryUpdateModel(part, Prefix, null, null);
            return Editor(part);
        }
    }
}

10. We can add the display and editor views in Visual Studio, using the "Add > View" context menu. First add a "DisplayTemplates" and "EditorTemplates" folder to the "Views" folder in the Tour project, and then right-click the EditorTemplates folder to add the view as follows.



The Add View dialog prompts with a few questions about the view. Name the view "Tour" and select "partial view" and "strongly typed" options, specifying "Tour.Models.TourPart" as the model type to pass to the view. You can also specify "Create" as the default view content, which will give you some sample HTML to customize for the editor view.

Edit the EditorTemplates\Tour.ascx file content so that it appears as follows:


        <fieldset>
            <legend>Fieldslegend>
           
            <div class="editor-label">
               
            div>
            <div class="editor-field">
               
               
            div>
           
            <div class="editor-label">
               
            div>
            <div class="editor-field">
               
               
            div>
           
            <p>
                <input type="submit" value="Create" />
            p>
        fieldset>




11. Repeat the "Add > View" step to create a Tour.ascx file under the "DisplayTemplates" folder, this time choosing "Empty" for the view content. 

Now edit the content of the file as follows (this will be used to display the Tour on the front-end:


<br/>
<p>TourCodep>: <b>$b><br />
<p>Descriptionp>:<br/>



12. To activate the Tour part, go to the "Features" section of the Orchard admin panel and enable it.




13. The Create name for the method is the convention for the initial data migration. It contains a single SchemaBuilder.CreateTable method that creates a "TourRecord" table with the TourCode and Description columns in addition to the ones from the basic ContentPartRecord.

Notice how we return 1, which is the version number for our migration.

Let's add another migration step to this to illustrate how you will later alter the existing schema and type metadata as your module evolves. In our case, we'll take this opportunity to add the feature that will enable the part to be attached to any content type. Add the following method to our data migration class:


public int UpdateFrom1() {
  ContentDefinitionManager.AlterPartDefinition("TourPart",
    builder => builder.Attachable());
  return 2;
}

This new migration is called "UpdateFrom1", which is the convention for upgrading from version 1. Your next migration should be called "UpdateFrom2" and return 3.

14. The defaults positions can be defined programmatically as well.  
This can be done from front end Admin> Manage Content Types > Content Parts > Edit
This can be done in a migration:


public int UpdateFrom2() {
  ContentDefinitionManager.AlterPartDefinition("TourPart", builder => builder
    .WithLocation(new Dictionary {
      {"Default", new ContentLocation { Zone = "primary", Position = "9"}},
      {"Editor", new ContentLocation { Zone = "primary", Position = "9"}},
    }));
  return 3;
}
15. Update Tour go to the "Features" section of the Orchard admin panel and enable it.


16. you may require to remove Global.ascx and Modify the web.config file from Tour Project accordingly  :




 xml version="1.0"?>

<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      assemblies>
    compilation>

    <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
      <namespaces>
        <add namespace="System.Web.Mvc"/>
        <add namespace="System.Web.Mvc.Ajax"/>
        <add namespace="System.Web.Mvc.Html"/>
        <add namespace="System.Web.Routing"/>
        <add namespace="System.Linq"/>
        <add namespace="System.Collections.Generic"/>
        <add namespace="Orchard.Mvc.Html"/>
      namespaces>
    pages>
  system.web>
  <system.web.extensions/>
configuration>


Special Thanks to Patrick’s Bytes and Writing a content part.

1 comment:

Selwyn said...

Very good blog for starting with Orchard framework.
It's a must ready blog.