Friday, 19 April 2013

How to Post a Request to a Web API Web Service?

My test Web API Method looks like this:

 [HttpPost]
        public HttpResponseMessage TestPost(string siteName, User user, string providerName)
        {
            var result = string.Format("sitename is {0}. user is {1}. providername is {2}", 
                siteName,
                user == null 
                ? "null. " 
                : " not null; " + (string.Format("email: {0}, pass: {1}", user.EmailAddress, user.Password)),
                providerName);

            return new HttpResponseMessage()
                {
                    Content = new StringContent(result)
                };
        }

If I had started the naming with "Post" then I didn't need to use "HttpPost" attribute; by convention it could have found it automatically.

How to write the Route Template?

 config.Routes.MapHttpRoute(
             name: "testpost",
             routeTemplate: "sites/{siteName}/User/TestPost/{providerName}",
             defaults: new
             {
                 controller = "User",
                 action = "TestPost",
                 providerName = UrlParameter.Optional
             });

As shown, the last parameter is optional so it accepts the below sample urls:

 http://www.domain.com/sites/sitename1/user/TestPost/provider1 http://www.domain.com/sites/sitename1/user/TestPost

Also, the {siteName} value is automatically mapped to the siteName input parameter of the web method.

As you can see, I don't put the User object in to the url template since it will be posted and not visible in the get.

How to Make Post Calls?
Now, I've written two test methods showing two approaches to make Post Calls to this service. First approach is easier and uses RestSharp and the second approach uses WebRequest.

.NET 4.5 provides a new class called HttpClient which makes it even easier to make such calls.

 [TestClass]
    public class WhenLoadingAUser
    {
        private readonly string _baseUrlForLuis = ConfigurationManager.AppSettings["BaseUrlFor.Luis"];
        
        /// 
        /// Approach 1 using RestSharp
        /// 
        [TestMethod]
        public void Should_post_successfully_with_valid_userDetailsList_usingRestSharp()
        {
            // arrange
            string url = string.Format("{0}/sites/{1}/User/TestPost/viper", this._baseUrlForLuis,
                "viper");

            var client = new RestClient(url);
            
            var request = new RestRequest(Method.POST)
                {
                    RequestFormat = DataFormat.Xml
                };


            // When reaches the Web Service, the below anonymous object gets mapped to the User object automatically.
            request.AddObject(new
                {
                    EmailAddress = "emailAddreess",
                    Password = "some password"
                });

            // act
            var response = client.Execute(request).Content;
        }

        /// 
        /// Approach 2 using WebRequest
        /// 
        [TestMethod]
        public void Should_post_successfully_with_valid_userDetailsList_usingWebRequest()
        {
            // arrange
            string url = string.Format("{0}/sites/{1}/User/TestPost/viper", this._baseUrlForLuis,
                "viper");

            var httpWReq = (HttpWebRequest)WebRequest.Create(url);
            httpWReq.Method = "POST";
            httpWReq.ContentType = "application/x-www-form-urlencoded";
            
            // not sure why the below format is required and not xml 
            string postData = "EmailAddress=email&Password=pass";

            // act
            PostData(httpWReq, postData);
            string response = GetResponseAsString(httpWReq);
        }

        private static string GetResponseAsString(HttpWebRequest httpWReq)
        {
            var response = (HttpWebResponse) httpWReq.GetResponse();

            return  new StreamReader(response.GetResponseStream()).ReadToEnd();
        }

        private static void PostData(HttpWebRequest httpWReq, string postData)
        {
            var encoding = new ASCIIEncoding();

            byte[] data = encoding.GetBytes(postData);

            httpWReq.ContentLength = data.Length;

            using (Stream stream = httpWReq.GetRequestStream())
            {
                stream.Write(data, 0, data.Length);
            }
        }
    }


How to make the post call with Fiddler?

The Content-Type header is important. Also, the data which is sent should be prepended with "=".



How to make a Post Call with just with a browser?

  1. Open a page that you know has the JQuery library; e.g. www.jquery.com 
  2. Click F12 and go to the Console tab where you can write JQuery codes
  3. Type "$.post('your url here',{'':'your data here'});

No comments: