Tuesday, 8 December 2009

Building an ASP.NET MVC E-Commerce app with Flux.net as the management tool – Part 2

Continuing the series I started yesterday, today we’ll look at getting some basic content structures defined in Flux along with executing some basic queries for that data from the MVC application.

As ever, follow along or get the source from codeplex here. If you’re using the source, don’t forget to re-create your database so the data in your app matches that created through this article.

Channel content type

As we’re going to be pulling data out of Flux from MVC without using URL re-writing or anything like that, we need a mechanism to address content in flux. We could use the data taxonomy tools to tag data in flux and query based on this, but this lacks form and structure, so I decided to define a channel content type that allows us to expose paths to data that we can easily query against.

For example, when we come to want to find the root categories for our site we’ll perhaps query against /categories and this will have entries for each category, which in turn will have products. We can then extend this later with channels like /content/news to define news articles we might want to list or /content/about to define a list of articles we want to show on the site.

The definition for the channel content type couldn’t be simpler – in the management project, we create a folder at /settings/types called Channel and create the following Content.type.config file;

<NodeType ID="Channel" Name="Content Channel" LimitVersions="1">


    <Relationships AddRoot="true">


We then add the form.aspx file to manage this content type;

<%@ Page Language="C#" Inherits="Deepcode.Flux.Core.UI.CMS.CMSContentForm" ValidateRequest="false"%>
<%@ Register TagPrefix="flux" Namespace="Deepcode.Flux.Core.UI.Controls" Assembly="Deepcode.Flux.Core"%>

<script runat="server">
    // Type ID being managed by this form
    protected override string FormTypeCode { get { return "Channel"; } }

    // Do form setup
    protected override void SetupForm(int ContentID, int ParentID)
        if (!Page.IsPostBack)
            fPath.NodeIDParent = ParentID;
            fPath.NodeIDPathed = ContentID;

    // Save fields to content object
    protected override void SaveContent(ref Deepcode.Flux.Core.Systems.CMS.ContentObject save)
        save.NodeName = this.fPath.Text;
        save.NodeTitle = this.fPageTitle.Text;

    // Load fields from content object
    protected override void LoadContent(Deepcode.Flux.Core.Systems.CMS.ContentObject load)
        this.fPath.Text = load.NodeName;
        this.fPageTitle.Text = load.NodeTitle;

<head id="Head1" runat="server">
    <link href="../../../admin/Asset/Style/GeneralStyle.css" rel="Stylesheet" type="text/css" />
<body class="nopadshaded">
<form id="form1" runat="server">
<flux:HostTable ID="HostTable1" runat="server">

<%-- Summary --%>
<flux:ValidationSummarySection ID="ValidationSummarySection1" runat="server" HeaderText="Please correct the following errors"/>

<%-- Form area --%>
    <flux:Section ID="Section1" runat="server" Title="Add/Edit Content Channel">
    <flux:ShadePadBox ID="ShadePadBox1" runat="server">

        <table cellspacing="0" cellpadding="3" border="0">
            <td><flux:NodePath runat="server" ID="fPath" Width="200px" MaxLength="100"/></td>

        <tr><td>Page Title:</td>
            <td><asp:TextBox runat="server" ID="fPageTitle" Width="300px" MaxLength="500"/></td>


<%-- Buttons --%>
<flux:Section ID="Section3" runat="server">
<flux:PadBox ID="PadBox1" CssClass="Pad5Button" runat="server">
    <asp:Button runat="server" ID="btnSave" Text="Save" OnClick="btnSave_Click" CssClass="button"/>&nbsp;&nbsp;&nbsp;
    <asp:Button runat="server" ID="btnCancel" Text="Cancel" OnClick="btnCancel_Click" CausesValidation="False"/>

<%-- Validators --%>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="fPath"
    ErrorMessage="You must specify the path for this page" Display="None"/>

<asp:RequiredFieldValidator ID="RequiredFieldValidator2" Runat="server" ControlToValidate="fPageTitle" 
    ErrorMessage="You must specify the title of this page" Display="None"/>



And our basic channel type is defined. We should now be able to use the manager to setup some basic channels – login to http://localhost:55000/ as admin@fluxcms.co.uk with a password of “password” and create some channels as below and then check them all in.


The next thing we need to do is get the MVC application to be able to see this data – to do this we add a reference in the MVC app to Deepcode.Flux.Core.dll (which you’ll find in management/bin). This gives us access to the Flux API, but before we can call it we also need to setup the flux.config in the MVC application. For this I created the /settings directory in the MVC application and copied flux.config from the other project.

Now, we can call the API. In the controller, I added the following (not very elegant) code;

public ActionResult Index()
    ContentObject [] list = ContentQuery.GetForParentID(-1);
    ViewData["list"] = list;
    return View();

Here, we’re doing a very basic query for all content at the root level, which should give us the categories and content nodes. For now, rather than creating a real model, I’ve just pumped this into view data ready for rendering, and in the view code I added;

    <%foreach(ContentObject obj in (ContentObject []) ViewData["list"]){%>

Which, … drum roll please …, gives us:


WHOOT! Our MVC app is getting it’s data from flux. So we’ve proven the point, we just now need to make it do something useful – but I’ll save that for the next post.

No comments:

Post a Comment