At TechEd 2004 in Amsterdam this year, I presented a couple sessions covering MCMS and SPS topics. In one of my sessions, I demonstrated how InfoPath Forms could be used to allow users to publish content to MCMS. Some customers want this functionality for a the following reasons:

  • The Authoring Connector, out of the box, only allows you to publish to one placeholder. Also, the authoring connector doesn't have client-side validation. The Authoring Connector can be customized as per the whitepaper published on the topic.
  • A structured, rich client approach to publishing content - InfoPath is easier to use and designing an InfoPath form to a MCMS Template is quite natural.
  • Client validation - You can achieve client validation with the browser approach if you write some custom javascript to validate content.
  • Offline publishing - authors can write their postings, save the infopath docs to their local drive, and then publish at a later date.

How you design your InfoPath publishing scenario is up to you. You can have an InfoPath form for each MCMS Template (1-to-1 mapping) or you can have a form that serves multiple templates.

During my TechEd session, I designed an InfoPath form “on the fly” by identifying my datasource as an XML Web Service. During design, I mapped a textbox to a parameter of the webmethod I wanted to invoke on submit. The Web Service took placeholder values (strings) as parameters and then created a posting in MCMS. The following sample takes in the different placeholder values for the WoodgroveNet “Press Release” template and then creates a posting in the “Press Releases” channel. You can imagine these being parameters themselves... in this sample, the template and channel values are hardcoded. Clearly, not a best practice. :-)

This sample should NOT be used in production. It just demonstrates how you can invoke a web service to publish content in MCMS. The one interesting piece of code is in purple - it demonstrates how you can authenticate to MCMS (which can run on another server) using the credentials of the user running the InfoPath application. This trick only works with Windows Integrated Authentication. In such a scenario, it's very useful because you don't have to store username/passwords and can inherit the rights of the user. Of course, you can only do this when you want to authenticate as the user invoking the web service - so for example, you can't do this when you invoke a web service in a typical ASP.NET application because then it will take the credentials of the ASP.NET worker process vs. the user who is browsing the site.

Also, because this is sample code, I haven't implemented error handling. For example, if the user invoking the web service doesn't have access to the “Press Release“ template, then it will return a rather ugly exception string... and won't do anything clever.

Last thing, needless to say, when the posting is submitted it will go through the typical MCMS workflow (or customized if you have customized it). If anyone has created an “InfoPath/MCMS“ integration pack, let me know! I would love to see it/hear about it.

  [WebMethod]
  public string addPressRelease(string title, string subtitle, string dateandlocation, string pressreleasecontent, string contactinfo)
  {
   try
   {
    CmsApplicationContext cac = new CmsApplicationContext();
    

    //Authenticate with the current user
    WindowsIdentity ident = HttpContext.Current.User.Identity as WindowsIdentity;
    cac.AuthenticateUsingUserHandle(ident.Token,PublishingMode.Update);


    //get the Press Release template and channel 
    Template cmsTemplate = (Template)cac.Searches.GetByPath("/Templates/WoodgroveNet/About Us Net/Press Release ASPX") as Template;
    Channel cmsChannel = cac.Searches.GetByUrl("/WoodgroveNet/About Us/Press Releases/") as Channel;

    Posting cmsPost = cmsChannel.CreatePosting(cmsTemplate);

    //set posting properties
    cmsPost.Name = title;
    cmsPost.DisplayName = title;

    //set placeholder values
    HtmlPlaceholder htmlTitle = cmsPost.Placeholders["Title"] as HtmlPlaceholder;
    htmlTitle.Html = title;

    HtmlPlaceholder htmlSubtitle = cmsPost.Placeholders["SubTitle"] as HtmlPlaceholder;
    htmlSubtitle.Html = subtitle;
    
    HtmlPlaceholder htmlDate = cmsPost.Placeholders["DateAndLocation"] as HtmlPlaceholder;
    htmlDate.Html = dateandlocation;

    HtmlPlaceholder htmlPress = cmsPost.Placeholders["PressReleaseContent"] as HtmlPlaceholder;
    htmlDate.Html = pressreleasecontent;

    HtmlPlaceholder htmlContact = cmsPost.Placeholders["ContactInformation"] as HtmlPlaceholder;
    htmlDate.Html = contactinfo;

    //submit the posting
    cmsPost.Submit();
    cac.CommitAll();
    return cmsPost.Guid;
   }
   catch (Exception exp)
   {
    return exp.ToString();
   }
  }