Click here to Skip to main content
15,893,594 members
Articles / Programming Languages / C# 4.0

Writing a P2P Snippet sharing Extension for Visual Studio 2010 (VSX 2010)

Rate me:
Please Sign up or sign in to vote.
4.50/5 (6 votes)
31 Mar 2010GPL311 min read 36.4K   332   21  
CodeXchange is a simple Visual Studio extension which allows you to create, edit and share snippets with your peers without leaving the Visual Studio 2010 IDE.
using System; 
using System.Threading;
using System.ComponentModel;
using System.Web.Services.Protocols;
using System.Windows.Forms;
using System.Net;
using System.Security;
using System.Text; 
using System.Runtime.InteropServices; 

using Sand.Services.CodeXchange.API.Interfaces;
using Sand.Services.CodeXchange.Client;
using Sand.Services.CodeXchange.Client.CodeXchangeService;

namespace Sand.Services.CodeXchange.API
{
	public class WebServiceExceptions
	{
		public const string IV_WEBEXCEPTION_TEXT	= "The server is not responding. Please try again.";
		public const string IV_WEBEXCEPTION_TITLE	= "Network Error";
		public const string IV_SOAPEXCEPTION_TEXT	= "The system could not log you on .Unknown username or password.";
		public const string IV_SOAPEXCEPTION_TITLE	= "Login Error";
		public const string IV_EXCEPTION_TEXT		= "An unknown error has occurred";
		public const string IV_EXCEPTION_TITLE		= "Unknown Error";
	}

	/// <summary>
	/// Summary description for ConnectionThread.
	/// </summary>
	public class CodeXchangeServiceLayer : Component
	{
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		/* EVENTS */
		public event EventHandler OnConnect;
		public event EventHandler OnRequestProviders;

		public event EventHandler OnRefreshMySnippetsRequest;

		/* PROVIDERS */
		private IConnectionProvider m_ConnectionProvider = null;
		private ISecurityProvider	m_SecurityProvider = null;

		/// <summary>
		/// The webservice response.
		/// </summary>
		private ServiceInfo serviceInfo = null;

		/// <summary>
		/// Creates a new instance of the <see cref="CodeXchangeServiceLayer"/> class.
		/// </summary>
		/// <param name="container"></param>
		public CodeXchangeServiceLayer (System.ComponentModel.IContainer container)
		{
			container.Add(this);
			InitializeComponent();
		}

		/// <summary>
		/// Creates a new instance of the <see cref="CodeXchangeServiceLayer"/> class.
		/// </summary>
		public CodeXchangeServiceLayer()
		{
			InitializeComponent();
		}

		/// <summary>
		/// Returns true is a connection with the webservice is available.
		/// </summary>
		public bool IsConnected
		{
			get { return (serviceInfo != null) ? true : false; }
		}

		public ServiceInfo ServiceInfo
		{
			get { return serviceInfo; }
		}

		/// <summary> 
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Component Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			components = new System.ComponentModel.Container();
		}
		#endregion


		public void Login ()
		{
			FireOnRequestProviders ();

            BackgroundWorker bgThread = new BackgroundWorker();

            bgThread.DoWork += new DoWorkEventHandler(bgThread_DoWork);
            bgThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgThread_RunWorkerCompleted);
            bgThread.RunWorkerAsync();
            

			///Perform the login on a different thread...
			//Thread thread = new Thread (new ThreadStart(BeginProcessing));
			//thread.Start();
		}

        void bgThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            FireOnServiceConnect();
        }

        void bgThread_DoWork(object sender, DoWorkEventArgs e)
        {
            BeginProcessing();
        }

		public void Logout ()
		{
			//Destroy the connection ...
			serviceInfo = null;

			SecurityProvider.ClearLoginCache ();
		}

		public Snippet GetSnippet (Guid snippetID )
		{
			if(!IsConnected)
				throw new NotConnectedException ();

			try
			{
				return CodeXchangeService.GetSnippet (snippetID);
			}
			catch(WebException) //Service not found or connection error.
			{
				MessageBox.Show (WebServiceExceptions.IV_WEBEXCEPTION_TEXT , 
					WebServiceExceptions.IV_WEBEXCEPTION_TITLE ,
					MessageBoxButtons.OK ,
					MessageBoxIcon.Error);
			}
			catch(Exception e)
			{
				MessageBox.Show ("Can't get snippet. The message was :" + e.Message.ToString(),
					"CodeXchange Addin" ,
					MessageBoxButtons.OK , 
					MessageBoxIcon.Information);
			}

			return null;
		}

		public Snippet[] GetMySnippets ()
		{
			if(!IsConnected)
				throw new NotConnectedException ();

			try
			{
				return CodeXchangeService.GetMySnippets ();
			}
			catch(WebException) //Service not found or connection error.
			{
				MessageBox.Show (WebServiceExceptions.IV_WEBEXCEPTION_TEXT , 
					WebServiceExceptions.IV_WEBEXCEPTION_TITLE ,
					MessageBoxButtons.OK ,
					MessageBoxIcon.Error);
			}
			catch(Exception e)
			{
				MessageBox.Show ("Your shared snippets list could not be retrieved. The message was :" + e.Message.ToString(),
					"CodeXchange Addin" ,
					MessageBoxButtons.OK , 
					MessageBoxIcon.Information);
			}
			
			return new Snippet[]{};	
		}

		public Snippet[] Search (string searchString)
		{
			if(!IsConnected)
				throw new NotConnectedException ();

			try
			{
				return CodeXchangeService.SearchSnippets (searchString);
			}
			catch(WebException) //Service not found or connection error.
			{
				MessageBox.Show (WebServiceExceptions.IV_WEBEXCEPTION_TEXT , 
					WebServiceExceptions.IV_WEBEXCEPTION_TITLE ,
					MessageBoxButtons.OK ,
					MessageBoxIcon.Error);
			}
			catch(Exception e)
			{
				MessageBox.Show ("Search Error.The message was :" + e.Message.ToString(),
					"CodeXchange Addin" ,
					MessageBoxButtons.OK , 
					MessageBoxIcon.Information);
			}
			
			return new Snippet[]{};	
		}

		public void RateSnippet (Guid snippetID, int vote)
		{
			if(!IsConnected)
				throw new NotConnectedException ();

			try
			{
				CodeXchangeService.RateSnippet (snippetID , vote);
			}
			catch(WebException) //Service not found or connection error.
			{
				MessageBox.Show (WebServiceExceptions.IV_WEBEXCEPTION_TEXT , 
					WebServiceExceptions.IV_WEBEXCEPTION_TITLE ,
					MessageBoxButtons.OK ,
					MessageBoxIcon.Error);
			}
			catch(Exception ex)
			{
				MessageBox.Show ("The snippet vote has not been cast .The message was :" + ex.Message.ToString(),
					"CodeXchange Addin" ,
					MessageBoxButtons.OK , 
					MessageBoxIcon.Information);
			}
		}

		public void AddSnippetComment (
			Guid snippetID, 
			string subject, 
			string text)
		{
			if(!IsConnected)
				throw new NotConnectedException ();

			try
			{
				CodeXchangeService.AddSnippetComment (
					snippetID ,
					subject , 
					text);
			}
			catch(WebException) //Service not found or connection error.
			{
				MessageBox.Show (WebServiceExceptions.IV_WEBEXCEPTION_TEXT , 
					WebServiceExceptions.IV_WEBEXCEPTION_TITLE ,
					MessageBoxButtons.OK ,
					MessageBoxIcon.Error);
			}
			catch(Exception ex)
			{
				MessageBox.Show ("Your comment could not be posted .The message was :" + ex.Message.ToString(),
					"CodeXchange Addin" ,
					MessageBoxButtons.OK , 
					MessageBoxIcon.Information);
			}
		}

		public Comment[] GetSnippetComments (Guid snippetID)
		{
			if(!IsConnected)
				throw new NotConnectedException ();

			try
			{
				return CodeXchangeService.GetSnippetComments (snippetID);
			}
			catch(WebException) //Service not found or connection error.
			{
				MessageBox.Show (WebServiceExceptions.IV_WEBEXCEPTION_TEXT , 
					WebServiceExceptions.IV_WEBEXCEPTION_TITLE ,
					MessageBoxButtons.OK ,
					MessageBoxIcon.Error);
			}
			catch(Exception ex)
			{
				MessageBox.Show ("Could not get Snippet commands. The message was :" + ex.Message.ToString(),
					"CodeXchange Addin" ,
					MessageBoxButtons.OK , 
					MessageBoxIcon.Information);
			}

			return new Comment[]{};
		}

		public bool RemoveSnippet (Guid snippetID)
		{
			if(!IsConnected)
				throw new NotConnectedException ();

			try
			{
				bool result = CodeXchangeService.RemoveSnippet (snippetID);

				if(result)
				{
					//Notify the user...
					if(MessageBox.Show ("Your snippet has been removed from CodeXchange\n\n Do you want to refresh your list of contributed snippets?" , 
						"CodeXchange Addin" ,
						MessageBoxButtons.YesNo , 
						MessageBoxIcon.Information) == DialogResult.Yes)
					{
						FireOnRefreshMySnippetsRequest ();
					}
				}
			}
			catch(WebException) //Service not found or connection error.
			{
				MessageBox.Show (WebServiceExceptions.IV_WEBEXCEPTION_TEXT , 
					WebServiceExceptions.IV_WEBEXCEPTION_TITLE ,
					MessageBoxButtons.OK ,
					MessageBoxIcon.Error);
			}
			catch(Exception ex)
			{
				MessageBox.Show ("The snippet could not be removed.The message was :" + ex.Message.ToString(),
					"CodeXchange Addin" ,
					MessageBoxButtons.OK , 
					MessageBoxIcon.Information);
			}

			return false;
		}

		public void PublishSnippet (
			Guid languageID, 
			Guid categoryID, 
			string summary, 
			string code, 
			string culture, 
			bool isPrivate, 
			bool hasCodeComments)
		{
			if(!IsConnected)
				throw new NotConnectedException ();

			try
			{
				CodeXchangeService.AddSnippet (languageID , 
					categoryID , 
					summary ,
					code , 
					culture ,
					isPrivate , 
					hasCodeComments);
			}
			catch(WebException) //Service not found or connection error.
			{
				MessageBox.Show (WebServiceExceptions.IV_WEBEXCEPTION_TEXT , 
					WebServiceExceptions.IV_WEBEXCEPTION_TITLE ,
					MessageBoxButtons.OK ,
					MessageBoxIcon.Error);
			}
			catch(Exception e)
			{
				MessageBox.Show ("The snippet could not be uploaded .The message was :" + e.Message.ToString(),
					"CodeXchange Addin" ,
					MessageBoxButtons.OK , 
					MessageBoxIcon.Information);
			}
		}

		public bool UpdateSnippet (
			Guid snippetID ,
			Guid languageID ,
			Guid categoryID , 
			string summary ,
			string code , 
			string culture ,
			bool isPrivate ,
			bool hasCodeComments) 
		{
			if(!IsConnected)
				throw new NotConnectedException ();

			try
			{
				bool result = CodeXchangeService.UpdateSnippet (
					snippetID ,
					languageID , 
					categoryID , 
					summary ,
					code , 
					culture ,
					isPrivate , 
					hasCodeComments);

				if (result)
				{
					//Notify the user...
					if(MessageBox.Show (
						"Your snippet has been updated\n\nDo you want to refresh your list of contributed snippets?" , 
						"CodeXchange Addin" ,
						MessageBoxButtons.YesNo , 
						MessageBoxIcon.Information) == DialogResult.Yes)
					{
						FireOnRefreshMySnippetsRequest ();
					}
				}
				else
				{
					MessageBox.Show ("The snippet could not be updated. Are you the snippet author?" ,
						"CodeXchange Addin" ,
						MessageBoxButtons.OK , 
						MessageBoxIcon.Information);
				}

				return result;
			}
			catch(WebException) //Service not found or connection error.
			{
				MessageBox.Show (WebServiceExceptions.IV_WEBEXCEPTION_TEXT , 
					WebServiceExceptions.IV_WEBEXCEPTION_TITLE ,
					MessageBoxButtons.OK ,
					MessageBoxIcon.Error);
			}
			catch(Exception e)
			{
				MessageBox.Show ("The snippet could not be updated. The message was :" + e.Message.ToString(),
					"CodeXchange Addin" ,
					MessageBoxButtons.OK , 
					MessageBoxIcon.Information);
			}

			return false;
		}

		private void BeginProcessing ()
		{
			//If we have an active internet connection ...
			if(ConnectionProvider.HasInternetConnection)
			{
				try
				{
					//Try to login to the webservice...
					serviceInfo = CodeXchangeService.Login ();
				}
				catch(WebException) //Service not found or connection error.
				{
					MessageBox.Show (WebServiceExceptions.IV_WEBEXCEPTION_TEXT , 
						WebServiceExceptions.IV_WEBEXCEPTION_TITLE ,
						MessageBoxButtons.OK ,
						MessageBoxIcon.Error);
				}
				catch(SoapException) //Unknow user or password!
				{
					MessageBox.Show (WebServiceExceptions.IV_SOAPEXCEPTION_TEXT, 
						WebServiceExceptions.IV_SOAPEXCEPTION_TITLE ,
						MessageBoxButtons.OK ,
						MessageBoxIcon.Error);

					//Nos aseguramos de que el cliente solicite de nuevo un
					//usuario y password al cliente.
					SecurityProvider.ClearLoginCache ();
				}
				catch(Exception e) //Service Exception ???
				{
					MessageBox.Show (e.Message + " " + e.StackTrace.ToString(), 
						WebServiceExceptions.IV_EXCEPTION_TITLE ,
						MessageBoxButtons.OK ,
						MessageBoxIcon.Error);
				}
			}

			//Notify to the main UI thread that we have connection with the WS.
			//FireOnServiceConnect ();
		}

		protected virtual CodeXchangeService CodeXchangeService
		{
			get
			{
				CodeXchangeService wsCodeXchange = new CodeXchangeService();

				//Preparamos el security header para identificar al usuario...
				SecurityHeader securityHeader = new SecurityHeader ();

				//Configuramos la obtencion de las credenciales a usar por el webserice ...
				SecurityProvider.ConfigureLoginCredentials ();

				//Lo configuramos en base a sus credenciales...
				securityHeader.Password = SecurityProvider.Password;
				securityHeader.Username = SecurityProvider.UserName;

				//Le agregamos las credenciales al webservice.
				wsCodeXchange.SecurityHeaderValue = securityHeader;

				//Attach credentials to the proxy to ensure it works on 
				wsCodeXchange.Proxy = ConnectionProvider.CreateProxy();

				return wsCodeXchange;
			}
		}

		protected virtual void CheckProviders ()
		{
			if (ConnectionProvider == null)
				throw new MissingProviderException ("Connection provider not set");

			if (SecurityProvider == null)
				throw new MissingProviderException ("Security provider not set");
		}

		public virtual IConnectionProvider ConnectionProvider
		{
			get { return m_ConnectionProvider;}
			set { m_ConnectionProvider = value;}
		}

		public virtual ISecurityProvider SecurityProvider
		{
			get { return m_SecurityProvider;}
			set { m_SecurityProvider = value;}
		}

		protected virtual void FireOnServiceConnect ()
		{ 
			if (OnConnect != null)
				OnConnect (this , EventArgs.Empty);
		}

		protected virtual void FireOnRequestProviders ()
		{ 
			if (OnRequestProviders != null)
				OnRequestProviders (this , EventArgs.Empty);
		}

		protected virtual void FireOnRefreshMySnippetsRequest ()
		{
			if (OnRefreshMySnippetsRequest != null)
				OnRefreshMySnippetsRequest (this , EventArgs.Empty);
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Software Developer
Spain Spain
Hi! I'm 22 years old. I live in a sunny mediterranian city called Barcelona.

I am a big fan of .NET and have been working with c# for a few years now.

Comments and Discussions