ebz351 integrating web services into your website with mcms 2002 arpan shah technical product...

34
EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Upload: aileen-briggs

Post on 28-Dec-2015

214 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

EBZ351

Integrating Web Services into Your Website with MCMS 2002Arpan Shah Technical Product Manager

Pat MillerMCMS Software Developer

Page 2: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Agenda

Rapid fire discussion aboutContent SyndicationContent AggregationThings to Consider whenusing Web Services

MCMS Web Services ScenariosCreating an XML Web Service with MCMSConsiderationsSecurity and Access Consuming Web ServicesCustom Placeholder Server Controls

Technologies

Page 3: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Syndication Defined

A distribution of content to various destinations for repurposing or republishing in another context.

Examples: To sell a comic strip, column, or television series for simultaneous publication in newspapers, periodicals, or independent television stations.

Aggregation Defined

Page 4: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Aggregation Defined

A collection of related content from various sources for repurposing or republishing in another context.

Examples:

Google, Yahoo, etc.CNN, ABC, NBC, etc.

Page 5: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Some Considerations

Scheduled versus Real Time

Push versus Pull

Authenticated versus Anonymous

RSS versus Web Service

Redundant vs. Centralized

Page 6: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Scheduled Versus Real Time

Scheduled Utilize resources off-peak

Handle large volumes

Trend analysis; all content available

Real TimeFreshest possible content

Potentially latent or even unavailable

Ad hoc; only get content requestedProvides for “Incremental Data Discovery”

Page 7: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Push Versus Pull

PushControl what, when, and who gets content

Synchronous for publisher

Typically Event-based

No wait time when needed by aggregator

PullSynchronous for consumer

Available at the convenience of the “puller”

No redundant store available

Puller may be selectivePrivate vs. Open Access

Page 8: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Authenticated Versus Anonymous

Authenticated accessRestricted access to content

Potentially fee based

Highly secure

Anonymous accessUnrestricted access to content

Promoted, publicized, exposed, broadcast

Typically free

RSS vs. Web Service

Page 9: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

RSS Versus Web Service

RSSStrict standard for organizing content

Powerful tools available for consumption

Requires an aggregator

Gaining popularity

Web ServiceAnything is possible, sky is the limit

Proprietary based upon public standards

Syndicate chooses level of publicity

Consumer must be technically savvy

Page 10: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Why Aggregate?

Aggregate Web sitesRich Content

Popular gathering place, visibility

Big Picture

No need to visit source (perhaps)

Simple hyperlinks are not sufficientPotential to lose visitor

Adding value to aggregate contentDifferentiate your site

Role of Web Services

Page 11: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Role Of Web Services with MCMS

PublishingExposing content to others to pull/consume

Example: www.microsoft.com/cmserver

Exposing an API to others for adding/changing/deleting content

Example: BotsConsulting

ConsumingConsuming external Web Services in your MCMS Site

Example: Consuming an RSS feed via a custom placeholder control

Example: Pushing data to a web service via workflow events

Custom Placeholders

Page 12: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Developing a Web Service with MCMS

MCMS Web Service Project

Publishing APIMust run on a machine with MCMS installed

CmsApplicationContext vs. CmsHttpContext

Searches

Performance

Retrieving content

Page 13: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Security Considerations

Anonymous

Authenticated

Page 14: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

demodemo

Exposing MCMS Exposing MCMS ContentContent

Page 15: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Updating Content

Mode

Security

Page 16: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

demodemo

Updating/Changing Updating/Changing ContentContent

Page 17: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Calling a Web Service from MCMS

DynamicMake a direct Web Service call for real-time Ensures real-time, accurate dataResource intensiveMust Rely on Web Service availability and handle otherwise

StaticStore Data in Local MCMS DatabaseWorkflow eventsHigh PerformanceMCMS Caching

Page 18: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

demodemo

BotsConsultingBotsConsulting

Pushing DataPushing Data

Page 19: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Demo Setup

Setup BOTS siteor you could use a Jobs Channel on your own site

Install Woodgrove Sample Data Site

An electronic version of the code used in this demo can be found at the end of this slide deck

Demo Characteristics

Page 20: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Push New Or Changed

Page 21: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Push New Or Changed

Page 22: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Push New Or Changed

Push Delete

Page 23: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Custom Placeholder Server Controls

Placeholder control — A control with dual runtime functionality:

Presentation mode: Display the contents of a placeholderAuthoring mode: Author the contents of a placeholder

Placeholder Base ClassSome of the methods you implement:

Loading Content into Placeholder ControlsPopulating Controls with Default ContentSaving Placeholder Content

Page 24: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

demodemo

Custom Placeholder Custom Placeholder Server ControlsServer Controls

Page 25: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Get The BookIn Depth Answers To Your Questions

TITLETITLE AvailableAvailable

Fall 2003Fall 2003

Microsoft® Content Microsoft® Content Management Management Server 2002 Server 2002 A Complete GuideA Complete Guide

Chapter 33 goes Chapter 33 goes into greater detail into greater detail on this very on this very example.example.

Community Resources

Page 26: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Community ResourcesCommunity Resources

NewsgroupsContent Management Server : http://www.microsoft.com/CMServer/community

SamplesGot Dot Net :http://www.gotdotnet.com

Stefan Gossner’s CMS Stuff site :http://mcms.stefan-gossner.de

Hands On Lab: EBZ-HOL02 in C141Developing Solutions Using MCMS 2002

Community Gathering

Page 27: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Community Resources

Community Resourceshttp://www.microsoft.com/communities/default.mspx

Most Valuable Professional (MVP)http://www.mvp.support.microsoft.com/

NewsgroupsConverse online with Microsoft Newsgroups, including Worldwidehttp://www.microsoft.com/communities/newsgroups/default.mspx

User GroupsMeet and learn with your peershttp://www.microsoft.com/communities/usergroups/default.mspx

Page 28: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

evaluations…evaluations…

Don’t forget to complete your online

Evaluation Form!

Page 29: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

© 2003 Microsoft Corporation. All rights reserved.© 2003 Microsoft Corporation. All rights reserved.This presentation is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY.This presentation is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY.

Page 30: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Code To Construct The Demos Follows

Note: This code is not intended to be viewed in PowerPoint but available electronically for the purpose of copying and pasting into VS.NET to reconstruct the demos discussed in this presentation.

Page 31: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Code BOTSJobWebService JobPosting.csusing System;using System;

namespace BOTSJobsWebServicenamespace BOTSJobsWebService{{

/// <summary>/// <summary>/// Summary description for JobPosting./// Summary description for JobPosting./// </summary>/// </summary>

[Serializable][Serializable] public class JobPostingpublic class JobPosting {{ //1. Public Properties//1. Public Properties public String JobEmployer;public String JobEmployer; public String JobPostingID;public String JobPostingID; public String JobPostingName;public String JobPostingName; public DateTime JobPostingStartDate;public DateTime JobPostingStartDate; public DateTime JobPostingExpiryDate;public DateTime JobPostingExpiryDate; public String JobTitle;public String JobTitle; public String JobDescription;public String JobDescription;

//2. Constructor, required by .NET Framework//2. Constructor, required by .NET Framework public JobPosting()public JobPosting() {{ }} }}}}

Page 32: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Code BOTSJobWebService PostJobsToBOTS.asmx.csusing System;using System;using System.Collections;using System.Collections;using System.ComponentModel;using System.ComponentModel;using System.Data;using System.Data;using System.Diagnostics;using System.Diagnostics;using System.Web;using System.Web;using System.Web.Services;using System.Web.Services;using Microsoft.ContentManagement.Publishing;using Microsoft.ContentManagement.Publishing;using Microsoft.ContentManagement.Publishing.Extensions.Placeholders;using Microsoft.ContentManagement.Publishing.Extensions.Placeholders;

namespace BOTSJobsWebServicenamespace BOTSJobsWebService{{

/// <summary>/// <summary>/// Summary description for PostJobsToBOTS./// Summary description for PostJobsToBOTS./// </summary>/// </summary>

[WebService (Namespace="http://botsconsulting.com")][WebService (Namespace="http://botsconsulting.com")] public class PostJobsToBOTS : System.Web.Services.WebServicepublic class PostJobsToBOTS : System.Web.Services.WebService

{{public PostJobsToBOTS()public PostJobsToBOTS(){{

//CODEGEN: This call is required by the ASP.NET Web Services Designer//CODEGEN: This call is required by the ASP.NET Web Services DesignerInitializeComponent();InitializeComponent();

}}

#region Component Designer generated code#region Component Designer generated code

//Required by the Web Services Designer //Required by the Web Services Designer private IContainer components = null;private IContainer components = null;

/// <summary>/// <summary>/// Required method for Designer support - do not modify/// Required method for Designer support - do not modify/// the contents of this method with the code editor./// the contents of this method with the code editor./// </summary>/// </summary>private void InitializeComponent()private void InitializeComponent(){{}}

/// <summary>/// <summary>/// Clean up any resources being used./// Clean up any resources being used./// </summary>/// </summary>protected override void Dispose( bool disposing )protected override void Dispose( bool disposing ){{

if(disposing && components != null)if(disposing && components != null){{

components.Dispose();components.Dispose();}}base.Dispose(disposing);base.Dispose(disposing);

}}

#endregion#endregion

// Public interface of Web Service// Public interface of Web Service [WebMethod][WebMethod] public string AddChangeJob(JobPosting job)public string AddChangeJob(JobPosting job) {{ trytry {{ //1. Grab an Authenticated Context in Update PublishingMode//1. Grab an Authenticated Context in Update PublishingMode // using the GetAuthenticatedCmsApplicationContext function// using the GetAuthenticatedCmsApplicationContext function // from Listing 25.1// from Listing 25.1 CmsApplicationContext cmsContextApp = CmsApplicationContext cmsContextApp = GetAuthenticatedCmsApplicationContext(PublishingMode.Update);GetAuthenticatedCmsApplicationContext(PublishingMode.Update);

//2. Grab the jobs Channel in which the Posting will exist//2. Grab the jobs Channel in which the Posting will exist // We must cast the result of the Searches object as a Channel// We must cast the result of the Searches object as a Channel Channel cmsChannel = Channel cmsChannel = cmsContextApp.Searches.GetByPath(cmsContextApp.Searches.GetByPath( "/Channels/botsconsulting/careers/jobs/")"/Channels/botsconsulting/careers/jobs/") as Channel;as Channel;

//3. Generate a consistent name for the Posting from data provided//3. Generate a consistent name for the Posting from data provided // The resulting name will look something like: Woodgrove.12345// The resulting name will look something like: Woodgrove.12345 string jobName = GenerateJobName(job.JobEmployer, job.JobPostingID);string jobName = GenerateJobName(job.JobEmployer, job.JobPostingID);

//4. Grab this Posting for update if it already exists//4. Grab this Posting for update if it already exists Posting cmsPosting = Posting cmsPosting = cmsContextApp.Searches.GetByPath(cmsContextApp.Searches.GetByPath( "/Channels/botsconsulting/careers/jobs/" + jobName)"/Channels/botsconsulting/careers/jobs/" + jobName) as Posting;as Posting;

//5. If no Posting was found, create one//5. If no Posting was found, create one if (cmsPosting == null)if (cmsPosting == null) {{ //6. Grab the Template upon which to create the Posting//6. Grab the Template upon which to create the Posting // We must cast the result of the Searches object as a Template// We must cast the result of the Searches object as a Template Template cmsTemplate = Template cmsTemplate = cmsContextApp.Searches.GetByPath(cmsContextApp.Searches.GetByPath( "/Templates/botsconsulting/JobDetail")"/Templates/botsconsulting/JobDetail") as Template;as Template;

//7. Create a new Posting//7. Create a new Posting cmsPosting = CreateNewPosting(cmsChannel, jobName, cmsTemplate);cmsPosting = CreateNewPosting(cmsChannel, jobName, cmsTemplate); }}

//8. Verify we have a Posting//8. Verify we have a Posting if (cmsPosting != null)if (cmsPosting != null) {{ //9. Set the Posting data, by synchronizing the Start/Expiry dates//9. Set the Posting data, by synchronizing the Start/Expiry dates // the postings automatically be published and expire together// the postings automatically be published and expire together cmsPosting.DisplayName = job.JobTitle.ToString();cmsPosting.DisplayName = job.JobTitle.ToString(); cmsPosting.StartDate = job.JobPostingStartDate;cmsPosting.StartDate = job.JobPostingStartDate; cmsPosting.ExpiryDate = job.JobPostingExpiryDate;cmsPosting.ExpiryDate = job.JobPostingExpiryDate;

//10. Grab the description placeholder//10. Grab the description placeholder HtmlPlaceholder cmsPlaceholder =HtmlPlaceholder cmsPlaceholder = cmsPosting.Placeholders["JobDescription"] as HtmlPlaceholder;cmsPosting.Placeholders["JobDescription"] as HtmlPlaceholder;

//11. Set the description placeholder's content//11. Set the description placeholder's content // The caller will include everything that they want to show// The caller will include everything that they want to show // in this single syndicated Posting in this field// in this single syndicated Posting in this field cmsPlaceholder.Html = job.JobDescription;cmsPlaceholder.Html = job.JobDescription;

//12. Submit the Posting//12. Submit the Posting // This will kick off whatever workflow BOTS has decided to// This will kick off whatever workflow BOTS has decided to // implement for the user we authenticated with// implement for the user we authenticated with cmsPosting.Submit();cmsPosting.Submit();

//13. Commit of all changes. If not explicitly called the//13. Commit of all changes. If not explicitly called the // disposition of changes is based upon RollbackOnSessionEnd// disposition of changes is based upon RollbackOnSessionEnd cmsContextApp.CommitAll();cmsContextApp.CommitAll(); }}

//14. Dispose of the standalone Application Context//14. Dispose of the standalone Application Context cmsContextApp.Dispose();cmsContextApp.Dispose();

//15. Let the caller of the Web Service know the job succeeded//15. Let the caller of the Web Service know the job succeeded return jobName + " successfully syndicated";return jobName + " successfully syndicated"; }} catch(Exception eError)catch(Exception eError) {{ //16. Write Error to File//16. Write Error to File LogErrorToFile(eError.Message.ToString());LogErrorToFile(eError.Message.ToString());

//17. Let the caller of the Web Service know an error occurred//17. Let the caller of the Web Service know an error occurred return job + eError.Message.ToString();return job + eError.Message.ToString(); }} }}

[WebMethod][WebMethod] public string DeleteJob(JobPosting job)public string DeleteJob(JobPosting job) {{ trytry {{ //1. Grab an Authenticated Context in Update PublishingMode//1. Grab an Authenticated Context in Update PublishingMode // using the GetAuthenticatedCmsApplicationContext function// using the GetAuthenticatedCmsApplicationContext function // from Listing 25.1// from Listing 25.1 CmsApplicationContext cmsContextApp = CmsApplicationContext cmsContextApp = GetAuthenticatedCmsApplicationContext(PublishingMode.Update);GetAuthenticatedCmsApplicationContext(PublishingMode.Update);

//2. Generate a consistent name for the Posting from data provided//2. Generate a consistent name for the Posting from data provided // The resulting name will look something like: Woodgrove.12345// The resulting name will look something like: Woodgrove.12345 string jobName = GenerateJobName(job.JobEmployer, job.JobPostingID);string jobName = GenerateJobName(job.JobEmployer, job.JobPostingID);

//3. Grab this existing Posting for syndicated deletion//3. Grab this existing Posting for syndicated deletion Posting cmsPosting = Posting cmsPosting = cmsContextApp.Searches.GetByPath(cmsContextApp.Searches.GetByPath( "/Channels/botsconsulting/careers/jobs/" + jobName)"/Channels/botsconsulting/careers/jobs/" + jobName) as Posting;as Posting;

//4. Check to see if the Posting was found, if it was delete it//4. Check to see if the Posting was found, if it was delete it if (cmsPosting != null)if (cmsPosting != null) {{ //7. Delete the Posting//7. Delete the Posting cmsPosting.Delete();cmsPosting.Delete();

//8. Submit the Posting//8. Submit the Posting // This will kick off whatever workflow BOTS has decided to// This will kick off whatever workflow BOTS has decided to // implement for the user we authenticated with// implement for the user we authenticated with cmsPosting.Submit();cmsPosting.Submit();

//9. Commit of all changes. If not explicitly called the//9. Commit of all changes. If not explicitly called the // disposition of changes is based upon RollbackOnSessionEnd// disposition of changes is based upon RollbackOnSessionEnd cmsContextApp.CommitAll();cmsContextApp.CommitAll(); }}

//10. Dispose of the standalone Application Context//10. Dispose of the standalone Application Context cmsContextApp.Dispose();cmsContextApp.Dispose();

//11. Let the caller of the Web Service know the job succeeded//11. Let the caller of the Web Service know the job succeeded return jobName + " successfully deleted";return jobName + " successfully deleted"; }} catch(Exception eError)catch(Exception eError) {{ //12. Write Error to File//12. Write Error to File LogErrorToFile(eError.Message.ToString());LogErrorToFile(eError.Message.ToString());

//13. Let the caller of the Web Service know an error occurred//13. Let the caller of the Web Service know an error occurred return job + eError.Message.ToString();return job + eError.Message.ToString(); }} }}

// Private helper Functions// Private helper Functions private void LogErrorToFile(string errorMessage)private void LogErrorToFile(string errorMessage) //**********************************************************************//********************************************************************** //Write Error to File//Write Error to File //**********************************************************************//********************************************************************** {{ trytry {{ //1. Write Error to File//1. Write Error to File System.IO.StreamWriter logFile =System.IO.StreamWriter logFile = new System.IO.StreamWriter(@"C:\LOGS\ErrorLog.txt", true);new System.IO.StreamWriter(@"C:\LOGS\ErrorLog.txt", true); logFile.WriteLine(errorMessage);logFile.WriteLine(errorMessage); logFile.Close();logFile.Close(); }} catch{}catch{} }}

private CmsApplicationContext GetAuthenticatedCmsApplicationContext private CmsApplicationContext GetAuthenticatedCmsApplicationContext (PublishingMode cmsMode)(PublishingMode cmsMode) //**********************************************************************//********************************************************************** //Adapted from Listing 25.1 Function to Create an Application Context//Adapted from Listing 25.1 Function to Create an Application Context //Create a new CmsApplicationContext and authenticate it//Create a new CmsApplicationContext and authenticate it //Pass the created Context back to the calling method//Pass the created Context back to the calling method //**********************************************************************//********************************************************************** {{ //1. Declare a Context variable//1. Declare a Context variable CmsApplicationContext cmsContextApp = null;CmsApplicationContext cmsContextApp = null; trytry {{ //2. Grab a new Application Context//2. Grab a new Application Context cmsContextApp = new CmsApplicationContext();cmsContextApp = new CmsApplicationContext();

//3. Assign current Windows User to a WindowsIdentity variable//3. Assign current Windows User to a WindowsIdentity variable // This will only work if IIS is set to Windows Authentication// This will only work if IIS is set to Windows Authentication // and Guest Access is enabled in the SCA// and Guest Access is enabled in the SCA System.Security.Principal.WindowsIdentity identCurrentUser = System.Security.Principal.WindowsIdentity identCurrentUser = System.Security.Principal.WindowsIdentity.GetCurrent();System.Security.Principal.WindowsIdentity.GetCurrent();

//4. Login to CMS//4. Login to CMS // Use the currently authenticated Windows User for credentials// Use the currently authenticated Windows User for credentials // Put Context into the PublishingMode passed to the function// Put Context into the PublishingMode passed to the function cmsContextApp.AuthenticateUsingUserHandle(identCurrentUser.Token,cmsContextApp.AuthenticateUsingUserHandle(identCurrentUser.Token, cmsMode);cmsMode);

//5. Return the Authenticated Context//5. Return the Authenticated Context return cmsContextApp;return cmsContextApp; }} catch(Exception eError)catch(Exception eError) {{ //6. Write Error to File//6. Write Error to File LogErrorToFile(eError.Message.ToString());LogErrorToFile(eError.Message.ToString());

//7. Return the null Context in the event of an error//7. Return the null Context in the event of an error return cmsContextApp;return cmsContextApp; }} }}

private Posting CreateNewPostingprivate Posting CreateNewPosting (Channel parentChannel, string newPostingName, Template cmsTemplate)(Channel parentChannel, string newPostingName, Template cmsTemplate) //**********************************************************************//********************************************************************** //Adapted from Listing 25.3 Function to Create New Posting//Adapted from Listing 25.3 Function to Create New Posting //Create a new Posting in the parentChannel using the newPostingName//Create a new Posting in the parentChannel using the newPostingName //based upon the cmsTemplate all passed to the function//based upon the cmsTemplate all passed to the function //Pass the created Posting back to the calling method//Pass the created Posting back to the calling method //**********************************************************************//********************************************************************** {{ //1. Declare a Posting variable//1. Declare a Posting variable Posting cmsPosting = null;Posting cmsPosting = null; trytry {{ //2. Determine if the user has sufficient rights to create//2. Determine if the user has sufficient rights to create // a Posting from the would be parent Channel// a Posting from the would be parent Channel if(parentChannel.CanCreatePostings)if(parentChannel.CanCreatePostings) {{ //3. Create the Posting using the Template passed to the function//3. Create the Posting using the Template passed to the function cmsPosting = parentChannel.CreatePosting(cmsTemplate);cmsPosting = parentChannel.CreatePosting(cmsTemplate);

//4. Validate successful creation//4. Validate successful creation if(cmsPosting != null)if(cmsPosting != null) {{ //5. Give it the Name passed to the function//5. Give it the Name passed to the function cmsPosting.Name = newPostingName;cmsPosting.Name = newPostingName; }} }} //6. Return the created Posting//6. Return the created Posting return cmsPosting;return cmsPosting; }} catch(Exception eError)catch(Exception eError) {{ //7. Write Error to File//7. Write Error to File LogErrorToFile(eError.Message.ToString());LogErrorToFile(eError.Message.ToString());

//8. Return the null Posting in the event of an error//8. Return the null Posting in the event of an error return cmsPosting;return cmsPosting; }} }}

private string GenerateJobName(string jobEmployer, string jobID)private string GenerateJobName(string jobEmployer, string jobID) //**********************************************************************//********************************************************************** //Concatenate JobEmployer and ID together to consistently form a name//Concatenate JobEmployer and ID together to consistently form a name //**********************************************************************//********************************************************************** {{ //1. Declare temp variable to hold jobname//1. Declare temp variable to hold jobname string jobName = "";string jobName = ""; trytry {{ //2. Strip out all spaces (could do any kind of tailoring here)//2. Strip out all spaces (could do any kind of tailoring here) jobName = jobEmployer.Replace(" ", "");jobName = jobEmployer.Replace(" ", "");

//3. Concatenate the GUID without the curly brackets to the//3. Concatenate the GUID without the curly brackets to the // Employer name separated with a period// Employer name separated with a period // This is done so that we can readily identify this Posting later// This is done so that we can readily identify this Posting later jobName += "." + jobID.Substring(1,36);jobName += "." + jobID.Substring(1,36);

//4. Return concatenated name//4. Return concatenated name return jobName.ToString();return jobName.ToString(); }} catch(Exception eError)catch(Exception eError) {{ //5. Write Error to File//5. Write Error to File LogErrorToFile(eError.Message.ToString());LogErrorToFile(eError.Message.ToString());

//6. Return empty name//6. Return empty name return jobName.ToString();return jobName.ToString(); }} }}

}}}}

Page 33: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Code WoodgroveNet CmsPosting_Approved in global.asax file//Be sure to include these two using statements at the top of the global.asax file//Be sure to include these two using statements at the top of the global.asax fileusing Microsoft.ContentManagement.Publishing;using Microsoft.ContentManagement.Publishing;using Microsoft.ContentManagement.Publishing.Extensions.Placeholders;using Microsoft.ContentManagement.Publishing.Extensions.Placeholders; // Private helper Functions// Private helper Functions private void WriteToLogFile(string logFileName, string logMessage)private void WriteToLogFile(string logFileName, string logMessage) //**********************************************************************//********************************************************************** //Write Message to File//Write Message to File //**********************************************************************//********************************************************************** {{ trytry {{ //Write Message to File//Write Message to File System.IO.StreamWriter logFile =System.IO.StreamWriter logFile = new System.IO.StreamWriter(@"C:\LOGS\" + logFileName.ToString() + ".txt", true);new System.IO.StreamWriter(@"C:\LOGS\" + logFileName.ToString() + ".txt", true); logFile.WriteLine(logMessage.ToString());logFile.WriteLine(logMessage.ToString()); logFile.Close();logFile.Close(); }} catch{}catch{} }}

protected void CmsPosting_Approved( Object sender, ChangedEventArgs e )protected void CmsPosting_Approved( Object sender, ChangedEventArgs e ) {{ trytry {{ //1. Grab the posting that is being Approved//1. Grab the posting that is being Approved Posting cmsPosting = e.Target as Posting;Posting cmsPosting = e.Target as Posting;

//2. Check to see if it is in the Woodgrove Careers channel//2. Check to see if it is in the Woodgrove Careers channel if (cmsPosting.Parent.Name == "Careers")if (cmsPosting.Parent.Name == "Careers") {{ //3. Grab the object that will pass our data as XML to BOTS//3. Grab the object that will pass our data as XML to BOTS BOTSJobWS.JobPosting jobToPost = new BOTSJobWS.JobPosting();BOTSJobWS.JobPosting jobToPost = new BOTSJobWS.JobPosting();

//4. Populate the Employer and Posting characteristic fields//4. Populate the Employer and Posting characteristic fields jobToPost.JobEmployer = "Woodgrove Bank";jobToPost.JobEmployer = "Woodgrove Bank"; jobToPost.JobPostingID = cmsPosting.Guid.ToString();jobToPost.JobPostingID = cmsPosting.Guid.ToString(); jobToPost.JobPostingName = cmsPosting.Name.ToString();jobToPost.JobPostingName = cmsPosting.Name.ToString(); jobToPost.JobPostingStartDate = cmsPosting.StartDate;jobToPost.JobPostingStartDate = cmsPosting.StartDate; jobToPost.JobPostingExpiryDate = cmsPosting.ExpiryDate;jobToPost.JobPostingExpiryDate = cmsPosting.ExpiryDate;

//5. Grab the approved Postings Title placeholder and populate the//5. Grab the approved Postings Title placeholder and populate the // JobTitle to pass to BOTS using the Html placeholder property // JobTitle to pass to BOTS using the Html placeholder property HtmlPlaceholder cmsPlaceholder =HtmlPlaceholder cmsPlaceholder = cmsPosting.Placeholders["Title"] as HtmlPlaceholder;cmsPosting.Placeholders["Title"] as HtmlPlaceholder; jobToPost.JobTitle = cmsPlaceholder.Html;jobToPost.JobTitle = cmsPlaceholder.Html;

//6. Grab the approved Postings JobDescription placeholder and//6. Grab the approved Postings JobDescription placeholder and // assign its Html to a temporary variable// assign its Html to a temporary variable cmsPlaceholder = cmsPosting.Placeholders["JobDescription"]cmsPlaceholder = cmsPosting.Placeholders["JobDescription"] as HtmlPlaceholder;as HtmlPlaceholder; string jobDescription = cmsPlaceholder.Html + "<br><br>";string jobDescription = cmsPlaceholder.Html + "<br><br>";

//7. Grab the approved Postings Qualifications placeholder and//7. Grab the approved Postings Qualifications placeholder and // append its Html to the temporary variable// append its Html to the temporary variable cmsPlaceholder = cmsPosting.Placeholders["Qualifications"]cmsPlaceholder = cmsPosting.Placeholders["Qualifications"] as HtmlPlaceholder;as HtmlPlaceholder; jobDescription += cmsPlaceholder.Html + "<br><br>";jobDescription += cmsPlaceholder.Html + "<br><br>";

//8. Grab the approved Postings ApplicationInstructions//8. Grab the approved Postings ApplicationInstructions // placeholder and append its Html to the temporary variable// placeholder and append its Html to the temporary variable cmsPlaceholder = cmsPlaceholder = cmsPosting.Placeholders["ApplicationInstructions"]cmsPosting.Placeholders["ApplicationInstructions"] as HtmlPlaceholder;as HtmlPlaceholder; jobDescription += cmsPlaceholder.Html + "<br><br>";jobDescription += cmsPlaceholder.Html + "<br><br>";

//9. Assign the temporary variable to the BOT JobDescription//9. Assign the temporary variable to the BOT JobDescription jobToPost.JobDescription = jobDescription.ToString();jobToPost.JobDescription = jobDescription.ToString();

//10. Create the proxy object to the PostJobToBOTS Web Service//10. Create the proxy object to the PostJobToBOTS Web Service BOTSJobWS.PostJobsToBOTS postJobToBOTS =BOTSJobWS.PostJobsToBOTS postJobToBOTS = new BOTSJobWS.PostJobsToBOTS();new BOTSJobWS.PostJobsToBOTS();

//11. Use the same credentials on BOTS that we are using in//11. Use the same credentials on BOTS that we are using in // Woodgrove. This is but one way to authenticate to the// Woodgrove. This is but one way to authenticate to the // Web Service.// Web Service. postJobToBOTS.Credentials =postJobToBOTS.Credentials = System.Net.CredentialCache.DefaultCredentials;System.Net.CredentialCache.DefaultCredentials;

//12. Invoke the BOTS WebMethod to Add or Change a Job//12. Invoke the BOTS WebMethod to Add or Change a Job postJobToBOTS.AddChangeJob(jobToPost);postJobToBOTS.AddChangeJob(jobToPost); }} }} catch(Exception eError)catch(Exception eError) {{ //13. Write Error to File//13. Write Error to File WriteToLogFile("ErrorLog.txt", eError.Message.ToString());WriteToLogFile("ErrorLog.txt", eError.Message.ToString()); }} }}

Page 34: EBZ351 Integrating Web Services into Your Website with MCMS 2002 Arpan Shah Technical Product Manager Pat Miller MCMS Software Developer

Code WoodgroveNet CmsPosting_Deleted in global.asax file [WebMethod][WebMethod] public string DeleteJob(JobPosting job)public string DeleteJob(JobPosting job) {{ trytry {{ //1. Grab an Authenticated Context in Update PublishingMode//1. Grab an Authenticated Context in Update PublishingMode // using the GetAuthenticatedCmsApplicationContext function// using the GetAuthenticatedCmsApplicationContext function // from Listing 25.1// from Listing 25.1 CmsApplicationContext cmsContextApp = CmsApplicationContext cmsContextApp = GetAuthenticatedCmsApplicationContext(PublishingMode.Update);GetAuthenticatedCmsApplicationContext(PublishingMode.Update);

//2. Generate a consistent name for the Posting from data provided//2. Generate a consistent name for the Posting from data provided // The resulting name will look something like: Woodgrove.12345// The resulting name will look something like: Woodgrove.12345 string jobName = GenerateJobName(job.JobEmployer, job.JobPostingID);string jobName = GenerateJobName(job.JobEmployer, job.JobPostingID);

//3. Grab this existing Posting for syndicated deletion//3. Grab this existing Posting for syndicated deletion Posting cmsPosting = Posting cmsPosting = cmsContextApp.Searches.GetByPath(cmsContextApp.Searches.GetByPath( "/Channels/botsconsulting/careers/jobs/" + jobName)"/Channels/botsconsulting/careers/jobs/" + jobName) as Posting;as Posting;

//4. Check to see if the Posting was found, if it was delete it//4. Check to see if the Posting was found, if it was delete it if (cmsPosting != null)if (cmsPosting != null) {{ //7. Delete the Posting//7. Delete the Posting cmsPosting.Delete();cmsPosting.Delete();

//8. Commit of all changes. If not explicitly called the//8. Commit of all changes. If not explicitly called the // disposition of changes is based upon RollbackOnSessionEnd// disposition of changes is based upon RollbackOnSessionEnd cmsContextApp.CommitAll();cmsContextApp.CommitAll(); }}

//9. Dispose of the standalone Application Context//9. Dispose of the standalone Application Context cmsContextApp.Dispose();cmsContextApp.Dispose();

//10. Let the caller of the Web Service know the job succeeded//10. Let the caller of the Web Service know the job succeeded return jobName + " successfully deleted";return jobName + " successfully deleted"; }} catch(Exception eError)catch(Exception eError) {{ //11. Write Error to File//11. Write Error to File WriteToLogFile("ErrorLog", eError.Message.ToString());WriteToLogFile("ErrorLog", eError.Message.ToString());

//12. Let the caller of the Web Service know an error occurred//12. Let the caller of the Web Service know an error occurred return job + eError.Message.ToString();return job + eError.Message.ToString(); }} }}