Friday, December 21, 2012

TFS 2010, VS 2010: No service host is available for the request; Service Unavailable – HTTP Error 503. The service is unavailable

TFS 2010 configuration issues: 

1. Service Unavailable – HTTP Error 503. The service is unavailable.

2. No service host is available for the request

If you are experiencing one of these errors while trying to configure TFS 2010, please see the solutions which worked for me. 

1. 503 error. 

- Check the application pools (You should have two created on the installation of TFS 2010) and make sure they are running. In my case the application pool was being stopped. The Identity I used for this was the same as the local Admin account I created on the Windows 2008 R2 server where TFS 2010 has been installed but for some unknown reason, as soon as I try to access the TFS from Visual studio or browser, the application pool goes into Stopped status. I changed the Identity to Local Service and then the Application pool wasn't being stopped but then I was getting the second error, described below when trying to access it from VS 2010 or browser. 

- I don't know if this is an issue but I altered between changing the .Net framework version to be used by the App pool from 2.0 to 4.0. I read many articles where some suggested using 2.0 while others suggested using 4.0. MSDN suggests using 4.0. Finally I ended up using 4.0 with the Identity as suggested below, then it worked for me.

2. No service host is available for the request. 

- In my case, I created a local admin on the Windows 2008 R2 server where the TFS 2010 was installed and tried to use the same as Identity for my application pools but for some unknown reason the application goes into stopped mode as soon as I tried to connect to TFS via VS 2010 or browser. Finally changing the account in TFS console to Network service and using the same for the App pool's Identity fixed it for me. 
So if none of the solutions online are working for you. Go ahead and browse the TFS Admin console, select the Application Tier, on the right hand side of Application Tier summary, click on Change Account and select the drop down list option for Network service. Restart your App pool (IIS if you need to). 


Hope this helps! 

Thursday, December 20, 2012

Team Foundation Server 2010 - Working folder is already in use

Issue: Working folder is already in use

Resolution:
1. Open up command prompt from Start >> Programs >> Visual Studio 2010 Tools.
2. Run the following commands:

- to check the existing work-spaces on your local machine:
   tf workspaces /server:http://:8080 /computer:-client
    tf workspaces /computer: /owner:* /format:detailed

- to delete those work-spaces
    tf workspace /delete /server:http://:8080 ;\

Try the delete for each of the workspace or for whichever workspace you don't need. If you deleted all, you can start afresh by creating new workspaces. 

Sunday, December 2, 2012

Consuming Oracle CRM OnDemand web services from .Net (C#)

Oracle CRM web services' documentation is not straight forward for implementation, at least I felt so. I had to figure it out the hard way but finally I was able to query and update. So here it is for anyone else embarking on the same path. 

1. Download the custom WSDL and NOT "Schema" after logging to CRM on demand website from the Admin > web services administration link. [Select Web Services 2.0 from the select services drop down box.]. Save it to a location on your drive and this is what you will reference from your "Add web reference" dialog box.

Note: This wsdl file will be huge (in tens of megs). 

2. In your project, select "Add web reference", type the path of the wsdl file on your drive. e.g. c:\oraclecrmsvc\contact.wsdl

You can find online examples of how to sign-in and make web service requests from this page - http://www.oracle.com/technetwork/indexes/samplecode/crmod-sample-522104.html. (R17Advsample1.zip - This has lot of examples about query, update, delete, etc., also to sign in).
 NOTE: Without signing in via the web service request, you cannot make request to query, update, delete or anything for that matter. 

Code: 


using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Services;
using XeroxOracleCrm.Svc.ContactSvc;
using System.Net;
using System.Data.SqlClient;
using System.Configuration;
using System.Text;
using System.Reflection; 
 
namespace XeroxOracleCrm.Svc
{
    [WebService(Namespace = "http://abc.Svc/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    public class XeroxOracleCrmBridgeService : System.Web.Services.WebService
    {
        public string server = ConfigurationManager.AppSettings["CrmUrl"]; 
        public string username;
        public string password;
        public string sessionId;
        public Cookie cookie;
 
        [WebMethod]
        public string Contacts(string customerId)
        {
            if (!string.IsNullOrEmpty(customerId))
            { 
                customerId = customerId.Trim();
                if (string.IsNullOrEmpty(customerId))
                {
                    return "Invalid Customer ID"; 
                }
            }
 
            string errorObtainingSession = Establish();
            if (!string.IsNullOrEmpty(errorObtainingSession))
            {
                return "Error obtaining Oracle CRM On Demand's session. Message: " + errorObtainingSession; 
            }
 
            string response = GetContacts(customerId); 
 
            Destroy();
 
            return response; 
        }
 

        #region Private Methods
        //You have to instantiate the properties in the request, which you want in the
        // response.
        private string GetContacts(string customerId)
        {
            Contact c = new Contact();
 
            ContactQueryPage_Input cqi = new ContactQueryPage_Input();
 
            ContactQuery cq = new ContactQuery();
            cq.ContactFirstName = new queryType();
            cq.ContactLastName = new queryType(); 
            cq.ContactEmail = new ContactSvc.queryType();
            cq.ContactFullName = new ContactSvc.queryType();
            cq.ContactType = new queryType();
            cq.CustomerId = new queryType(); 
            cq.Id = new ContactSvc.queryType();
            cq.AccountId = new ContactSvc.queryType();
     
            cq.AssistantPhone = new ContactSvc.queryType();
            cq.HomePhone = new ContactSvc.queryType();
            
            cq.CustomText0 = new queryType();
            cq.CustomText1 = new queryType();
            cq.CustomText2 = new queryType();
            cq.CustomText3 = new queryType();
            cq.CustomText4 = new queryType();
            cq.CustomText5 = new queryType();
            cq.CustomText6 = new queryType();
            cq.CustomText7 = new queryType();
            cq.CustomText8 = new queryType(); 
            cq.QualifiedDate = new ContactSvc.queryType();
            cq.OwnerFullName = new ContactSvc.queryType();
            cq.LastCallDate = new ContactSvc.queryType();
            cq.LastActivityDate = new ContactSvc.queryType();
            cq.Gender = new ContactSvc.queryType();
            cq.CreatedDate = new ContactSvc.queryType();
            cq.ModifiedDate = new ContactSvc.queryType();
            cq.CreatedById = new ContactSvc.queryType();
            cq.CreatedByEMailAddr = new ContactSvc.queryType();
 
            cq.ExternalSystemId = new ContactSvc.queryType(); 
            cq.IndexedDate0 = new queryType();  
            cq.IndexedBoolean0 = new queryType();
            cq.IndexedCurrency0 = new queryType();
            cq.IndexedLongText0 = new queryType();
            cq.IndexedNumber0 = new queryType();
            cq.IndexedPick0 = new queryType();
            cq.IndexedPick1 = new queryType();  
            cq.IndexedPick2 = new queryType();
            cq.IndexedPick3 = new queryType();
            cq.IndexedPick4 = new queryType(); 
            cq.IndexedPick5 = new queryType();
            cq.IndexedShortText0 = new queryType(); 
            cq.IndexedShortText1 = new queryType(); 
            
            cq.ContactRole = new ContactSvc.queryType();
 
//You can use whatever query you want. Play with it. 
            cq.searchspec = "([ExternalSystemId] = '" + customerId +"')";
 
            ListOfContactQuery lcq = new ContactSvc.ListOfContactQuery();
            lcq.pagesize = "5";
            lcq.startrownum = "0";
            lcq.recordcountneeded = true;
            lcq.Contact = cq;
 
            cqi.ListOfContact = lcq;
 
            c.Url = GetURL();
            try
            {
                ContactQueryPage_Output co = c.ContactQueryPage(cqi);
                if(co.ListOfContact != null && co.ListOfContact.Contact != null && co.ListOfContact.Contact.Length > 0)
                {
                    ContactData cData = co.ListOfContact.Contact[0];
                    PropertyInfo[] properties = cData.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
                    StringBuilder sbContactData = new StringBuilder(); 
                    foreach (PropertyInfo property in properties)
                    {
                        sbContactData.AppendLine(property.Name + ": " + property.GetValue(cData, null));
                    }
                    return sbContactData.ToString(); 
                }
                return string.Empty; 
            }
            catch (Exception ex)
            {
                return ex.ToString();
            }
        }
  
        private string GetURL()
        {
            if (sessionId == null)
            {
                throw new Exception("No session has been established!");
            }
            
            return server + "/Services/Integration;jsessionid=" + sessionId;
        }
 
        private string GetLogInURL()
        {
            return server + "/Services/Integration?command=login";
        }
 
        private string GetLogOffURL()
        {
            return server + "/Services/Integration?command=logoff";
        }
 
        private string Establish()
        {
            try
            {
                // create a container for an HTTP request
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(GetLogInURL());
 
                // username and password are passed as HTTP headers
                req.Headers.Add("UserName"ConfigurationManager.AppSettings["CrmUserName"]);
                req.Headers.Add("Password"ConfigurationManager.AppSettings["CrmPassword"]);
 
                // cookie container has to be added to request in order to 
                // retrieve the cookie from the response. 
                req.CookieContainer = new CookieContainer();
 
                // make the HTTP call
                HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
                if (resp.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    // store cookie for later...
                    cookie = resp.Cookies["JSESSIONID"];
                    if (cookie == null)
                    {
                        throw new Exception("No JSESSIONID cookie found in log-in response!");
                    }
                    sessionId = cookie.Value;
                }
            }
            catch (Exception ex)
            {
                return ex.Message; 
            }
            return ""; 
        }
 
        private void Destroy()
        {
            // create a container for an HTTP request
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(GetLogOffURL());
 
            // reuse the cookie that was received at Login
            req.CookieContainer = new CookieContainer();
            req.CookieContainer.Add(cookie);
 
            // make the HTTP call
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            if (resp.StatusCode != System.Net.HttpStatusCode.OK)
            {
                throw new Exception("Logging off failed!");
            }
            // forget current session id
            sessionId = null;
        }
 
        #endregion
    }
}


Note: Use fiddler to see the requests and responses. 



Good luck!

Thursday, October 4, 2012

Add Soap Header to dynamic Web Service call using Reflection in C#.Net


I've been struggling with this one for a while.

Situation: We need to call different web services on the fly (dynamically). The service maybe hosted in Java or Linux or whatever environment. We know the URLs, Soap header names, etc.

Solution 1: Read the WSDL from the URL, then compile the assembly and get the object. Using reflection, invoke the web method. Same for Soap Header too. Use reflection, instantiate the soap header, set the properties.

Solution 2: If instantiating the SOAP Header as said in Solution 1 is an issue for some reason then write a custom SOAP extension to add the Header to the out going SOAP message.

The links below show how to do it (for solution 2).
IMPORTANT: I tried the solution suggested in link-1 and I was getting the "XML not well formed", inner exception: Root element missing error. After a lot of tweaking (with fiddler) and searching on google, found the article on link-2, below which overrides the "Before Deserialize" and copies the tweaked SOAP to the output stream. That got me rid of the XML well formed error.

1. http://forums.asp.net/t/1137408.aspx
2. http://blog.encoresystems.net/articles/how-to-capture-soap-envelopes-when-consuming-a-web-service.aspx

Thanks to the posters of the above links!!!

NOTE: Another issue I had was not including the xmlns (namespace) in the SOAP header. Do include it.

Let me know if you still have issues.

Happy Dynamic web service calling.
=============================
Below is my code for the Soap Extension


    public class CarrierCallbackServiceExtension : SoapExtension
    {
        private bool outgoing = true;
        private bool incoming = false;
        private Stream outputStream;
        public Stream oldStream;
        public Stream newStream; 
 
        public override System.IO.Stream ChainStream(System.IO.Stream stream)
        {
            outputStream = stream;
            oldStream = stream; 
            newStream = new MemoryStream();
            return newStream; 
        }
 
        public override object GetInitializer(Type serviceType)
        {
            return null; 
        }
 
        public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
        {
            throw new NotImplementedException();
        }
 
        public override void Initialize(object initializer)
        {
            return; 
        }
 
        public void WriteInput(SoapMessage message)
        {
            Copy(oldStream, newStream);
            newStream.Position = 0; 
        }         void Copy(Stream from, Stream to)         {             TextReader reader = new StreamReader(from);             TextWriter writer = new StreamWriter(to);             writer.WriteLine(reader.ReadToEnd());             writer.Flush();         }                  public override void ProcessMessage(SoapMessage message)         {             switch (message.Stage)             {                 case SoapMessageStage.BeforeSerialize:                     string clientResponse = GetXmlFromCache();                      break;                 case SoapMessageStage.BeforeDeserialize:                     WriteInput(message);                     break;                  case SoapMessageStage.AfterDeserialize:                     break;                  case SoapMessageStage.AfterSerialize:                     {                         string soapBodyString = GetXmlFromCache();                         int startPosition = soapBodyString.IndexOf("StringComparison.OrdinalIgnoreCase);                         int endPosition = soapBodyString.Length - startPosition;                         soapBodyString = soapBodyString.Substring(startPosition, endPosition);                         string xmlVersionString = @"";                                                  string soapEnvelopeBeginString =                             @"";                         string soapEnvHeaderString = @"";                         string soapEnvHeaderString2 = "
";                         string soapEnvHeaderString3 = "";                         Stream appOutputStream = new MemoryStream();                         StreamWriter soapMessageWriter = new StreamWriter(appOutputStream);                         soapMessageWriter.Write(xmlVersionString);                         soapMessageWriter.Write(soapEnvelopeBeginString);                         // The heavy-handed part - forcing the right headers AND the uname/pw :)                         soapMessageWriter.Write(soapEnvHeaderString);                         soapMessageWriter.Write("USERNAMESTRING");                         soapMessageWriter.Write(soapEnvHeaderString2);                         soapMessageWriter.Write("PASSWORDSTRING");                         soapMessageWriter.Write(soapEnvHeaderString3);                         // End clubbing of baby seals                         // Add the soapBodyString back in - it's got all the closing XML we need.                         soapMessageWriter.Write(soapBodyString);                         // write it all out.                         soapMessageWriter.Flush();                         appOutputStream.Flush();                         appOutputStream.Position = 0;                                                  XElement xe = XElement.Load(appOutputStream);                                                   XDocument xdoc = new XDocument(new XDeclaration("1.0""utf-8""yes"));                         xdoc.Add(xe);                         string output = StringWritingHelper(xdoc);                         //xdoc.Save(outputStream);                         //StreamReader reader = new StreamReader(appOutputStream);                         StreamWriter writer = new StreamWriter(this.outputStream);                         //writer.Write(reader.ReadToEnd());                         writer.Write(output);                         writer.Flush();                         appOutputStream.Close();                         this.outgoing = false;                         this.incoming = true;                         break;                      }             }         }         private string StringWritingHelper(XDocument sourceDocument)         {             StringBuilder sbResponse = new StringBuilder();             using (StringWriterUtf8 stringWriter = new StringWriterUtf8(sbResponse))             {                 sourceDocument.Save(stringWriter);             }             return sbResponse.ToString();         }         private string GetXmlFromCache()         {             newStream.Position = 0;             string soapResponse = ExtractFromStream(newStream);             return soapResponse;          }         private string ExtractFromStream(Stream target)         {             if (target != null)             {                 return (new StreamReader(target)).ReadToEnd();              }             return string.Empty;          }     }

Monday, March 12, 2012

(Tricky) C#.NET, SQL Server interview questions

1. What is the difference between classic ASP and ASP.NET ?
(my answer) ASP.NET has the .NET framework part which includes CLS and CLR. CLS - has all the libraries. CLR provides the ability to convert MSIL to binary code and take care of bunch of other stuff like Garbage collection, etc.

2. Principles of OOPS.
Inheritance, Polymorphism, Abstraction, Encapsulation.

3. What is the need of Encapsulation?

4. Is C# Array type a value type or reference type. - It is a REFERENCE type.

5. Is C# string a reference type or a value type - It is a REFERENCE type.

6. If a stored procedure has a variable defined as varchar(10) but hasn't been initialized. Then what would be the value of LEN(variable)? - It will be NULL.

7. If there is a nested Transaction in sql stored procedure and the inner Transaction rolls back, what will happen at the commit of the outer Transaction?

8. How to do authentication with Windows Authentication for a website? If there are 100 users how you would you authenticate their access permissions?

9. Difference between a session and view state
- Session is global whereas view state is for the particular aspx page.
- View state is sent back to client (browser) every time in an encrypted hidden variable but the value of session variable is passed in as a cookie or appended to the URL.

10. How to implement caching?

11. Would you choose JSON or XML for web service return format?
JSON - because it is light weight compared to XML.

12. Is WSDL alone enough to connect to an open source (not .NET) web service?

13. Heap vs Stack allocation of memory in .NET. 

Friday, March 2, 2012

Website vs Web service

The basic difference of a website vs a web service is that:

Website/Web application: Returns a slew of web pages served by a web server (e.g. IIS) that are human readable via a browser. 

Web Service: Returns data in various formats (xml, json, etc), depending on the protocol (SOAP, HTTP,etc) that is machine understandable, usually for other applications to use that data. If you want to have that data human-readable then a web page that consumes that data, has to be built which is then rendered by the browser. 

Programmers - web service returns pure objects whereas web site renders data in web pages which can be rendered by the browser.