4

We have developed an ASP.Net Webforms Application, some sort of web shop. Some of the pages only have editorial content, news, articles etc. These contents come from the database right now and are hard to edit for the content writers.

My boss wants me to check if we can use Composite C1 as a CMS and integrate it with the Project.

I have looked into it now and played around with it for some days now, but I am still unsure if it is a good idea and how exactly I would integrate the two systems.

  • The navigation menu and some other permanent parts of the website are drawn from the database and have to be shown on the editorial pages as well.
  • We use SEO friendly URLs (Routing) and the URLs have to stay the same.

How complex will it be to merge the two projects? Will I have to give up the old ASP.Net Website Project and put all my sites into the Composite project? Or will it be possible to run both side by side, even though they have shared navigation menus etc?

Will Routing be a problem?

Has anyone done this kind of merge before? Any experience would be a great help.

magnattic
  • 12,638
  • 13
  • 62
  • 115
  • are you able to run the existing functionality as UserControls instead? – Pauli Østerø Oct 31 '11 at 21:01
  • I am not sure, many things are in controls already, but there are also things like application-wide caching, the Routing (with variables being passed to the pages) etc) Will I get this to work somehow in Composite? – magnattic Oct 31 '11 at 21:44
  • I am concerned that I will lose a lot of the flexibility I have with a Webforms Project if I switch my whole project to Composite. Is this unreasonable? Can I do everything in the C1 project that I do now in my ASP.Net Website Project? – magnattic Oct 31 '11 at 21:46

1 Answers1

5

C1 is using Webforms to host its content, so there is nothing you can't do which you're doing now within your webforms project. You can use Webforms Masterpages as templates for your content, and routing is fully supported, either through adding as many custom routes as you want or just overriding the default c1 page route. Or relying on the PathInfo Api, where unmatched parts of the url will be available to use on the page that matches the longest possible part of the url. You can also use Razor (.cshtml) in C1 if you like that new syntax from Microsoft.

You can also turn things around, and choose to render content from C1 on your own existing pages. This code here shows how a standard WebForm .aspx page can be used to render content from a specific page in C1

public class BaseContentTeaserPage : Page
{
    private Guid _pageId;

    protected PlaceHolder plc;

    protected override void OnPreInit(EventArgs e)
    {
        _pageId = Guid.Parse(Request.QueryString["pageId"]);

        using (new DataScope(PublicationScope.Published, new CultureInfo("en-GB")))
        {
            using (var data = new DataConnection())
            {
                PageRenderer.CurrentPage = data.Get<IPage>().Single(p => p.Id == _pageId);

                var urlData = new PageUrlData(PageRenderer.CurrentPage);
                urlData.PathInfo = Request.QueryString["pathInfo"];

                Context.Items["C1_PageUrl"] = urlData;
            }
        }

        base.OnPreInit(e);
    }

    protected override void OnLoad(EventArgs e)
    {
        using (new DataScope(PublicationScope.Published, new CultureInfo("en-GB")))
        {
            var content = DataFacade.GetData<IPagePlaceholderContent>().Single(p => p.PageId == _pageId);

            var helper = new PageRendererHelper();
            var mapper = (IXElementToControlMapper)helper.FunctionContext.XEmbedableMapper;
            var doc = helper.RenderDocument(content);
            var body = PageRendererHelper.GetDocumentPart(doc, "body");

            addNodesAsControls(body.Nodes(), plc, mapper);

            if (Page.Header != null)
            {
                var head = PageRendererHelper.GetDocumentPart(doc, "head");
                if (head != null)
                {
                    addNodesAsControls(head.Nodes(), Page.Header, mapper);
                }
            }
        }

        base.OnLoad(e);
    }

    private static void addNodesAsControls(IEnumerable<XNode> nodes, Control parent, IXElementToControlMapper mapper)
    {
        foreach (var node in nodes)
        {
            var c = node.AsAspNetControl(mapper);
            parent.Controls.Add(c);
        }
    }

    protected override void Render(HtmlTextWriter writer)
    {
        var markupBuilder = new StringBuilder();
        using (var sw = new StringWriter(markupBuilder))
        {
            base.Render(new HtmlTextWriter(sw));
        }

        string xhtml = markupBuilder.ToString();

        using (Profiler.Measure("Changing 'internal' page urls to 'public'"))
        {
            xhtml = PageUrlHelper.ChangeRenderingPageUrlsToPublic(xhtml);
        }

        using (Profiler.Measure("Changing 'internal' media urls to 'public'"))
        {
            xhtml = MediaUrlHelper.ChangeInternalMediaUrlsToPublic(xhtml);
        }

        writer.Write(xhtml);
    }
}
Pauli Østerø
  • 6,878
  • 2
  • 31
  • 48
  • So basically your advice would be: Put all functionality into controls, throw your old project away and use C1 as the main project, right? – magnattic Oct 31 '11 at 22:52
  • without knowing anything really about your project its next to impossible to give concrete specific advice. If its because you just want to use C1 to manage content, you can also choose to turn things around and render content from C1 in your existing project. All you need is to setup a correct context for C1 to query its data and you can output it wherever you want. Edited my answer to show how easy that is as well. – Pauli Østerø Oct 31 '11 at 22:58
  • Sounds interesting, do you know any articles/examples about how exactly to do this? – magnattic Oct 31 '11 at 23:03