Sunday, November 9, 2014

Visual Studio Intellisense not Working (VS2012, VS2013)

The Intellisense feature in Visual Studio 2012 and 2013 do not seem to work well. It breaks down time to time and has almost become a big headache! So, what would be the easiest solution? to Google? Oh No!!!, thousands of options and answers and many of them don't really work! But if you are fine with deleting your Visual Studio settings without spoiling any of your code then this should be the easiest way for you!

1) In your start menu search "%AppData%" and enter. You will be taken to "Roaming" folder. (Make sure you have closed your Visual Studio Instance before start doing this.)

2) Go to "Microsoft > Visual Studio" inside the "Roaming" folder.

3) Here you will see the the visual studio versions installed in your machine as folder names.

4) If you are having intellisense issues with VS2012 then rename the "11.0" folder. For VS2013, "12.0" is the corresponding folder.

5) Now start a new Visual Studio instance and you are ready to go!

6) If everything works fine, just delete the renamed folder.

Happy Coding!!

Tuesday, January 14, 2014

Integrating WebEx Video Conferencing with ASP.NET - Creating a new WebEx Meeting


This article illustrates how to ingrate WebEx Web Conferencing solution into a .net application. WebEx is cool and powerful compared with the other video conferencing solutions I have worked with. We will be using the WebEx XML API in our demonstration.

The first thing you need to do is to sign up with the Cisco developer site.  After you get registered click on the "Try WebEx APIs" sub menu under "Develop and Test" menu. There you will find some information you need to access the API. You will be sending the Site URL,  Site ID, Partner ID as parameters on your request. XML Service URL is to where you will be sending your request to. Then you need to create a host account for you to schedule meetings.


Now you are ready to use your API! Let's create a web application in Visual Studio (Web Forms or MVC). I'm using a web forms application for rapid development. In this post we will only be covering about how to create a webex meeting.

The only thing you need to know when coding is how to create and send a web request and how to process an XML document.You don't need to know much! ;-). This is the request XML I will be passing to the WebEx XML Service (see above image for XML Service URL ).

  
yourhostemailaddress@live.com ******** 243585 g0webx! yourhostemailaddress@live.com
<!-- pass123 Test 4 Lushanthan myattendee@live.com true true true 900 20 42
-->
Please note that some of the tags have been commented as those features are not supported for a basic account. The 'MeetingType' tag is commented because we don't have an existing meeting template created. We can use 'MeetingType' if we already have templates created on our WebEx site with default set of attendees and in case if we want to use that. We have left out the 'confName' tag and the 'startDate' tag empty as we will be providing a UI for the user to enter those details and we will be binding them programmatically. We can also add more attendees if needed.

Below given code shows the "Create Meeting" button click event. Please note that we are getting the conference name and the attendee email list as user inputs from the form.

protected void Button1_Click(object sender, EventArgs e)
        {
            WebResponse response = null;
            Stream dataStream = null;

            try
            {
                string confName = txtMeetingName.Text;
                string attendeeList = txtAttendees.Text;

                //Get Emails separated by commas
                string[] emails = attendeeList.Split(',');

                //Create New Meeting and reload page                
                string strXMLServer = @"https://apidemoeu.webex.com/WBXService/XMLService";

                WebRequest request = WebRequest.Create(strXMLServer);
                // Set the Method property of the request to POST.
                request.Method = "POST";
                // Set the ContentType property of the WebRequest.
                request.ContentType = "application/x-www-form-urlencoded";

                XmlDocument xmlDocument = new XmlDocument();
                try
                {
                    XmlReader reader = new XmlTextReader(Server.MapPath("Xml/CreateMeeting.xml"));
                    xmlDocument.Load(reader);
                }
                catch (Exception)
                {
                    throw;
                }

                XmlNamespaceManager manager = new XmlNamespaceManager(xmlDocument.NameTable);
                manager.AddNamespace("serv", "http://www.webex.com/schemas/2002/06/service");

                //Set Meeting metadata
                xmlDocument.SelectSingleNode("/serv:message/body/bodyContent/metaData/confName", manager).InnerText = txtMeetingName.Text;
                xmlDocument.SelectSingleNode("/serv:message/body/bodyContent/schedule/startDate", manager).InnerText = DateTime.Now.ToString();

                //Set Attendees
                XmlNode attendeeListNode = xmlDocument.SelectSingleNode("/serv:message/body/bodyContent/participants/attendees", manager);

                if (attendeeListNode != null)
                {
                    foreach (string email in emails)
                    {
                        try
                        {
                            XmlNode attendeeNode = xmlDocument.CreateNode(XmlNodeType.Element, "attendee", "");
                            attendeeNode.InnerXml = "" + email.Split('@')[0] + "" + email.Trim() + "";
                            attendeeListNode.AppendChild(attendeeNode);
                        }
                        catch (Exception)
                        {
                            throw new Exception("Please insert valid email addresses");
                        }
                    }
                }
               
                byte[] byteArray = Encoding.UTF8.GetBytes(xmlDocument.OuterXml);

                // Set the ContentLength property of the WebRequest.
                request.ContentLength = byteArray.Length;

                // Get the request stream.
                dataStream = request.GetRequestStream();
                // Write the data to the request stream.
                dataStream.Write(byteArray, 0, byteArray.Length);
                // Close the Stream object.
                dataStream.Close();
                // Get the response.
                response = request.GetResponse();

                // Get the stream containing content returned by the server.
                dataStream = response.GetResponseStream();
                XmlDocument xmlReply = null;

                if (response.ContentType == "application/xml" || response.ContentType == "text/xml;charset=UTF-8")
                {
                    xmlReply = new XmlDocument();
                    xmlReply.Load(dataStream);
                }

                //Process Meeting Response
                string result = this.ProcessMeetingResponse(xmlReply);

                if (!string.IsNullOrEmpty(result))
                {
                    lblMessage.Text = result;
                }
            }
            catch (HttpException)
            {
                lblMessage.ForeColor = System.Drawing.Color.Red;
                lblMessage.Text = "An Http Exception occured. Please try again later.";
            }
            catch (XmlException)
            {
                lblMessage.ForeColor = System.Drawing.Color.Red;
                lblMessage.Text = "Xml Exception occured. Please try again later.";
            }
            catch (Exception ex)
            {
                lblMessage.ForeColor = System.Drawing.Color.Red;
                lblMessage.Text = ex.Message;
            }
            finally
            {
                if (dataStream != null)
                {
                    dataStream.Close();
                }
                if (response != null)
                {
                    response.Close();
                }
            }
            imgLoader.Style.Add("display", "none");
        }

Ok now! As you can see in line 86 in the code snippet ProcessMeetingResponse method needs to be implemented. Before implementing that method we need to know about the meeting reponse XML that we will be receiving from the WebEx XML Service for both the success case and the failure case. Here is a sample response we will be receiving on failure.

  
    
      FAILURE
      The user or site does not support this meeting type
      PRIMARY
      110002
    
  
  
    
  


And on success we will receive an XML with some more data.

  
    
      SUCCESS
      PRIMARY
    
  
  
    
      98691968
      
        
          https://www.webex.com/calendarurl1/j.php?ED=48591508&UID=BA24987F&ICS=MIFH&ST=12
        
        
          https://www.webex.com/calendarurl1/j.php?ED=48591508&UID=BA24987F&ICS=MIFA&ST=12
        
      
      f10324e2af4823c278fa1a6efadc426c
    
  


Note that in the success response we will get the meeting key and the icalender url which we can use to bind with our email calenders.

On ProcessMeetingRespons() method we return an empty string on success and a error reason on any exception.Error reason can be found inside the "serv:reason" tag in the failure XML.

Resources:
WebEx XML API Overview 
https://developer.cisco.com/site/tech/communication-collaboration/webex/webex-developer/develop-test/xml-api/reference/

WebEx XML API Reference Guide
https://developer.cisco.com/site/tech/communication-collaboration/webex/webex-developer/develop-test/xml-api/reference/

https://developer.cisco.com/fileMedia/download/1d70807a-6431-4a80-b13a-aa8faa4575b7

P.S: The sample mentioned in this article is done using the WebEx XML API. However, the same functionality can also be implemented using the WebEx URL API.