Thursday, November 5, 2015

SharePoint Configuration Error (An exception of type Microsoft.SharePoint.Upgrade.SPUpgradeException was thrown. Failed to call GetTypes on assembly Microsoft.Office.InfoPath.Server )

I have been facing this error when running the SharePoint Configuration Wizard, and was able to find a solution after googling for some time.

This error occurs when Office 2013 is installed with SharePoint 2010 and when you try to Configure SharePoint Central Administration.

Error:

Failed to create the configuration database. An exception of type Microsoft.SharePoint.Upgrade.SPUpgradeException was thrown. Additional exception information: 
Failed to call GetTypes on assembly Microsoft.Office.InfoPath.Server, Version=14.0.0.0, Culture=neutral, 
PublicKeyToken=71e9bce111e9429c. Could not load file or assembly 'Microsoft.Office.InfoPath, Version=15.0.0.0, 
Culture=neutral, PublicKeyToken=71e9bce111e9429c' or one of its dependencies. The system cannot find the file specified.
 Could not load file or assembly 'Microsoft.Office.InfoPath, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' 
or one of its dependencies. The system cannot find the file specified. Could not load file or assembly 'Microsoft.Office.InfoPath, 
Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' or one of its dependencies. The system cannot find 
the file specified. Could not load file or assembly 'Microsoft.Office.InfoPath

The solution is to remove the below given folders from C:\Windows\assembly\GAC_MSIL (Check the "Important" section below)

1. Policy.14.0.Microsoft.Office.InfoPath
2. Policy.14.0.Microsoft.Office.InfoPath.Client.Internal.Host
3. Policy.14.0.Microsoft.Office.InfoPath.FormControl

Now re-run the Configuration Wizard!

Important:
You may not be able to access the this folder (C:\Windows\assembly\GAC_MSIL) directly. Check out my earlier blog post on how to access the GAC folder. Cheers!


Accessing the GAC folder structure using Windows Explorer

Many of us have accessed the Global Assembly Cache (GAC) for troubleshooting purposes. But when viewed using the Windows Explorer (C:\Windows\assembly), all the assemblies are rendered in a different way by the Operating System. This is not the actual physical structure of the GAC folder.


Try coping the same path and paste it on a browser (Chrome or Firefox) or access the path using command line, You might be surprised to see the real structure of the GAC folder. What you see in the Windows explorer is an aggregated view of the inner folders












To enable viewing the actual folder structure of the GAC from the windpows explorer, go to the Windows registry editor (regedit), create a string value key by the name "DisableCacheViewer" inside "HKEY_LOCAL_MACHINE\Software\Microsoft\Fusion" and set the value to "1". Now browse the same folder using windows explorer.


The earlier mentioned default nature of the GAC folder is achieved using the shell namespace extension. By using this, you can create custom functionality for windows explorer.



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.


Sunday, August 25, 2013

நெஞ்சே எழு!


Tuesday, April 16, 2013

Returning a partial view on a MVC Ajax Form submit


In my previous post we talked about returning a Json object on a MVC Ajax form submit. There we had to write several Java-Script methods in order to process the response. In that case it was just about whether are registration (form1) was successful or not. But assume we need to show another form (form2) (without redirection), do some data filling there and submit it and that all these things have to be in Ajax.

One way you could achieve this, is to have both these forms in our html page and do a jquery show  and a hide on those forms. below given is the javascript code if are implementing this in our previous example.
function RegisterSuccess(data) {
    try {   
        if (data.Status == "0") {          
            $('#form1').hide();
            $('#form2').show();          
        } else {           
            $(".msg").addClass('error');
            $(".msg").html(data.Message);
        }
    } catch (e) {
    }
}

If we need to auto fill up some of the information in form2 from the database, we need to write javascript code to set the values for each of those fields. I remeber Scott Hanselman , saying "People who can read java-scripts are weird people!" (people who write too!) in one of this videos. So what if a js library writes all these javascripts for us and that we only need to return a view. Yes, Ajax.BeginForm takes care of all that. You just need to set the UpdateTargetId and the LoadingElementId parameters.

Ok now. Time for some coding! This is how are razor view look like.
@model AjaxMvc4.Models.RegisterModel
@{
    ViewBag.Title = "Register";
}

@ViewBag.Title.

Create a new account.

@using (Ajax.BeginForm("Register", "Account", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "formContent", LoadingElementId = "loader" })) { @Html.AntiForgeryToken() @Html.ValidationSummary()
Registration Form
  1. @Html.LabelFor(m => m.UserName) @Html.TextBoxFor(m => m.UserName)
  2. @Html.LabelFor(m => m.Password) @Html.PasswordFor(m => m.Password)
  3. @Html.LabelFor(m => m.ConfirmPassword) @Html.PasswordFor(m => m.ConfirmPassword)
}
@section Scripts { @Scripts.Render("~/bundles/jqueryval") }


In the controllers instead of returning a Json object we return a partial view. We can even pass a model and set if we need to fill some of the information in the new form (either from the database or from the previous model posted).



        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                try
                {
                    WebSecurity.CreateUserAndAccount(model.UserName, model.Password);
                    WebSecurity.Login(model.UserName, model.Password);

                    UserModel user = new UserModel();
                    user.UserName = model.UserName;

                    return PartialView("_UserContactDetailsPartial", user);               
                }
                catch (MembershipCreateUserException e)
                {                   
                    ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
                }
            }
            return PartialView("_ErrorPartial");    
        }

User Details Partial View :
@model AjaxMvc4.Models.UserModel





@using (Ajax.BeginForm("Account", "ContactInformation", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "formContent", LoadingElementId = "loader" }))
{
    @Html.ValidationSummary(true)

    
Contact Details
User Name
@Html.DisplayFor(model => model.UserName) @Html.HiddenFor(model => model.UserName)
First Name
@Html.EditorFor(model => model.FirstName) @Html.ValidationMessageFor(model => model.FirstName)
Last Name
@Html.EditorFor(model => model.LastName) @Html.ValidationMessageFor(model => model.LastName)
Email Address
@Html.EditorFor(model => model.Email) @Html.ValidationMessageFor(model => model.Email)
Phone Number
@Html.EditorFor(model => model.PhoneNo) @Html.ValidationMessageFor(model => model.PhoneNo)
Mobile Number
@Html.EditorFor(model => model.Mobile) @Html.ValidationMessageFor(model => model.Mobile)
Address
@Html.EditorFor(model => model.Address) @Html.ValidationMessageFor(model => model.Address)

}
Don't forget to reference the jquery.validate.min.js and jquery.validate.unobtrusive.min.js for your ajax form to work!

Monday, April 15, 2013

Simple asp.net MVC Ajax Form Application

For this purpose, I'm using Microsoft asp.net MVC4 application.

Step1. As always, add a new project (Not an empty web project).







 Step2. Choose Internet Application from the project template.














Step3. As it is not an empty web project, there will be a set of code generated for you. For example the log in and the registration modules (Models, Controllers and Views). We are planning to alter them into Ajax forms.

Step4. Ok now, lets do some coding. We'll try to change the registration module. Go to register.cshtml in the Account folder inside the Views folder. Instead of the normal Html.BeginForm , change that to Ajax.BeginForm.

There are some slight changes you need to make when it comes to Ajax.BeginForm method.  You need to provide the HttpMethod and some Java-script functions as AjaxOptions other than controller and the action name. I have provided Java script methods for OnBegin, OnSuccess, OnComplete and OnFailure events. (Check Step 6 for JS implementaions)









































Step5. We also need to change the controller, since we are planning to return Json Objects so that we can process them in are Java scripts. I have made the return type as "JsonResult" instead of "ActionResult". ActionResult Class is parent class of JsonResult Class. However, I have opted for JsonResult so that I can be more specific (Register action will only return Jsons). Although, inside my "Register" action the registration process is the same, instead of doing a return View(), I do a return Json(). I need to process this Json at client side, according to the format I specify here. Here I'm simply returning a Status and a Message in my Json.


Step6. Now that we have written the code to send an ajax request and process it in the server side, we now need to handle the response in the client side. Below shown are my Java Script method implementations mentioned in step4. In my RegisterBegin() and RegisterComplete() methods I'm just showing and hiding a progress bar. RegisterFailure() method (called by OnFailure event) prompts for error with the HttpStatus Code. Note that this method gets fired only  for Http errors. Not for our application errors. We need to handle our application errors within the RegisterSuccess() method as they also get return with  http status success 200 (which triggers the OnSuccess event).

In our RegisterSuccess() method we differentiate the success registration and errors in registration based on the Status codes in our Json Object (Check Controller Code). If success, we are redirecting to the home page and if not we are showing the error message passed from the controller via the json object.



Step7. We are ready to launch now. Run the application and start registering. You will see a progress bar once you click on the submit button, and the success message on a successful registration. Try some exception scenarios as well! Good Luck!