Friday, 5 July 2013

Twitter API 1.1 Integration with MVC in c#

Twitter has recently stopped its support to its API version 1 from 11th June,2013. Many developers including me are using that API in our application which was retrieving tweets as per a given hash tag (#).
After done a bit of googling I found that there is no way but to move our application to the new Twitter API version 1.1
I feel the primary road block for using the new Twitter API is its OAuth authentication. I hardly found any site wrote much about this. Anyways, first I had to register my Application to get four keys which had been used for OAuth authentication. The registration site is
https://dev.twitter.com/apps
Now I had the four keys.

Consumer key
Consumer secret
Access token
Access token secret

I was all ready to start writing my OAuth authentication class now. Firstly, I added the four keys in my web.config file.

    
    
    
    

Then I created a class named TwitterHelper.cs as follows
using System.Net;
using System.Security.Cryptography;
using System.IO;

public class TwitterHelper
    {
        public const string OauthVersion = "1.0";
        public const string OauthSignatureMethod = "HMAC-SHA1";

        public Twitter(string consumerKey, string consumerKeySecret, string accessToken, string accessTokenSecret)
        {
            this.ConsumerKey = consumerKey;
            this.ConsumerKeySecret = consumerKeySecret;
            this.AccessToken = accessToken;
            this.AccessTokenSecret = accessTokenSecret;
        }

        public string ConsumerKey { set; get; }
        public string ConsumerKeySecret { set; get; }
        public string AccessToken { set; get; }
        public string AccessTokenSecret { set; get; }
        
        public string GetTweets(string twitterHashTag, int count)
        {
            string resourceUrl = string.Format("https://api.twitter.com/1.1/search/tweets.json");
            var requestParameters = new SortedDictionary();
            requestParameters.Add("q", twitterHashTag);
            requestParameters.Add("count", count.ToString());
            requestParameters.Add("result_type", "mixed");
            var response = GetResponse(resourceUrl, "GET", requestParameters);
            return response;
        }
 
        private string GetResponse(string resourceUrl, string methodName, SortedDictionary requestParameters)
        {
            ServicePointManager.Expect100Continue = false;
            WebRequest request = null;
            string resultString = string.Empty;
            
            request = (HttpWebRequest)WebRequest.Create(resourceUrl + "?" + requestParameters.ToWebString());
            request.Method = methodName;
            request.ContentType = "application/x-www-form-urlencoded";
            
            
            if (request != null)
            {
                var authHeader = CreateHeader(resourceUrl, methodName, requestParameters);
                request.Headers.Add("Authorization", authHeader);

                var response = (HttpWebResponse)request.GetResponse();
                using (var sd = new StreamReader(response.GetResponseStream()))
                {
                    resultString = sd.ReadToEnd();
                    response.Close();
                }
            }
            return resultString;
        }

        private string CreateOauthNonce()
        {
            return Convert.ToBase64String(new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString()));
        }

        private string CreateHeader(string resourceUrl, string methodName, SortedDictionary requestParameters)
        {
            var oauthNonce = CreateOauthNonce();
            // Convert.ToBase64String(new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString())); 
            var oauthTimestamp = CreateOAuthTimestamp();
            var oauthSignature = CreateOauthSignature(resourceUrl, methodName, oauthNonce, oauthTimestamp, requestParameters);
            //The oAuth signature is then used to generate the Authentication header. 
            const string headerFormat = "OAuth oauth_nonce=\"{0}\", oauth_signature_method=\"{1}\", " + "oauth_timestamp=\"{2}\", oauth_consumer_key=\"{3}\", " + "oauth_token=\"{4}\", oauth_signature=\"{5}\", " + "oauth_version=\"{6}\"";
            var authHeader = string.Format(headerFormat, Uri.EscapeDataString(oauthNonce), Uri.EscapeDataString(OauthSignatureMethod), Uri.EscapeDataString(oauthTimestamp), Uri.EscapeDataString(ConsumerKey), Uri.EscapeDataString(AccessToken), Uri.EscapeDataString(oauthSignature), Uri.EscapeDataString(OauthVersion));
            return authHeader;
        }
        private string CreateOauthSignature(string resourceUrl, string method, string oauthNonce, string oauthTimestamp, SortedDictionary requestParameters)
        {
            //firstly we need to add the standard oauth parameters to the sorted list 
            requestParameters.Add("oauth_consumer_key", ConsumerKey);
            requestParameters.Add("oauth_nonce", oauthNonce);
            requestParameters.Add("oauth_signature_method", OauthSignatureMethod);
            requestParameters.Add("oauth_timestamp", oauthTimestamp);
            requestParameters.Add("oauth_token", AccessToken);
            requestParameters.Add("oauth_version", OauthVersion);
            var sigBaseString = requestParameters.ToWebString();
            var signatureBaseString = string.Concat(method, "&", Uri.EscapeDataString(resourceUrl), "&", Uri.EscapeDataString(sigBaseString.ToString()));
            
            var compositeKey = string.Concat(Uri.EscapeDataString(ConsumerKeySecret), "&", Uri.EscapeDataString(AccessTokenSecret));
            string oauthSignature;
            using (var hasher = new HMACSHA1(Encoding.ASCII.GetBytes(compositeKey)))
            {
                oauthSignature = Convert.ToBase64String(hasher.ComputeHash(Encoding.ASCII.GetBytes(signatureBaseString)));
            }
            return oauthSignature;
        }
        private static string CreateOAuthTimestamp()
        {
            var nowUtc = DateTime.UtcNow;
            var timeSpan = nowUtc - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
            var timestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString(); return timestamp;
        }
    }

    public static class Extensions
    {
        public static string ToWebString(this SortedDictionary source)
        {
            var body = new StringBuilder();
            foreach (var requestParameter in source)
            {
                body.Append(requestParameter.Key);
                body.Append("=");
                body.Append(Uri.EscapeDataString(requestParameter.Value));
                body.Append("&");
            } //remove trailing '&' 
            body.Remove(body.Length - 1, 1); return body.ToString();
        }
    }
For showing tweets in the View, I created a custom model class named TwitterModel.cs as follows
public class TwitterModel
    {
        public string Id { get; set; }
        public string Content { get; set; }
        public string AuthorName { get; set; }
        public string AuthorUrl { get; set; }
        public string ProfileImage { get; set; }
        public DateTime? Published { get; set; }
    }
That's all, I got ready to use the TwitterHelper class and TwitterModel class in my controller to retrieve the tweets as per the Twitter Hash Tag (#)
public ActionResult Index()
{
     List tweets = GetTweets("#twitter");
     return View(tweets);
}

public List GetTweets(string twitterHashTag)
        {
            
            List lstTweets = new List();

            // New Code added for Twitter API 1.1
            if (!string.IsNullOrEmpty(twitterHashTag))
            {
                var twitter = new TwitterHelper(ConfigurationManager.AppSettings["OauthConsumerKey"],
                                                                ConfigurationManager.AppSettings["OauthConsumerKeySecret"],
                                                                ConfigurationManager.AppSettings["OauthAccessToken"],
                                                                ConfigurationManager.AppSettings["OauthAccessTokenSecret"]);
                var response = twitter.GetTweets(evt.TwitterHashtag, 100);
                dynamic timeline = System.Web.Helpers.Json.Decode(response);
                foreach (var tweet in timeline)
                {
                    System.Web.Helpers.DynamicJsonArray tweetJson = tweet.Value as System.Web.Helpers.DynamicJsonArray;
                    if (tweetJson != null && tweetJson.Count() > 0)
                        foreach (System.Dynamic.DynamicObject item in tweetJson)
                        {
                            TwitterModel tModel = new TwitterModel();
                            tModel.Id = ((dynamic)item).id.ToString();
                            tModel.AuthorName = ((dynamic)item).user.name;
                            tModel.AuthorUrl = ((dynamic)item).user.url;
                            tModel.Content = ((dynamic)item).Text;
                            string publishedDate = ((dynamic)item).created_at;
                            publishedDate = publishedDate.Substring(0, 19);
                            tModel.Published = DateTime.ParseExact(publishedDate, "ddd MMM dd HH:mm:ss", null);

                            tModel.ProfileImage = ((dynamic)item).user.profile_image_url;
                            lstTweets.Add(tModel);
                        }
                  }
            }
            return lstTweets;
        }
Finally, everything is done, I bound the Model object in the View and was able to retrieve the tweets by twitter hashtag. User can search using other twitter parameter also and would be able to retrieve the tweets.

I got the reference for OAuth class from the following blog. Please go through it for more explanation
http://johnnewcombe.net/blog/post/12

References : http://johnnewcombe.net/blog/post/12

Tuesday, 23 April 2013

Upload and Download Image in Windows Azure Blob Storage in MVC 3

I have been spent quite a bit time to find the solution in one of my projects, finally, I am able to crack it in the following way.
  1. Firstly create a separate controller class in the MVC project for managing the the operations with Images. I named it as AlbumController.
  2. This controller  class contains the action to handle the HttpPostedFile coming from View.
  3. I created a Model class for containing all the necessary methods for handling the operations with the Images.
I am going to describe in details for better understanding
public class AlbumController
    {
        private DiskFileStore fileStore = new DiskFileStore();

        public string AsyncUpload()
        {
            try
            {
                return fileStore.SaveUploadedFile(Request.Files[0]);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
     }
In the above code AsyncUpload is the action which is being used to handle the file submitted. I have created a custom model class named DiskFileStore looks like the following. I am using JQuery AsyncUpload plugin to upload my images in my project.

using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using System.Configuration;

internal class DiskFileStore
    {
         private string _downloadsFolder = HostingEnvironment.MapPath("~/Photos/");
        
         public string SaveUploadedFile(HttpPostedFileBase fileBase)
        {
            try
            {
                CloudStorageAccount csa = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["AzureStorageConnectionString"]);
                CloudBlobClient blobStorage = csa.CreateCloudBlobClient();

                var identifier = Guid.NewGuid();
                string identifierInLower = identifier.ToString().ToLower();

                string fileNameFromRequest = fileBase.FileName.ToLower();
                string fileExtension = fileNameFromRequest.Substring(fileNameFromRequest.IndexOf('.'));

                string originalFileName = identifierInLower + fileExtension;

                CloudBlobContainer cbcMain = blobStorage.GetContainerReference("photos");
                cbcMain.CreateIfNotExist();
                CloudBlob mainblob = cbcMain.GetBlobReference(originalFileName);
                mainblob.UploadFromStream(fileBase.InputStream);

                
                // Abhishek: Download the uploaded blob to local file to show the image at UI                
                CloudBlob savedBlob;
                savedBlob = blobStorage.GetBlobReference("photos/" + originalFileName);
                savedBlob.DownloadToFile(_downloadsFolder + originalFileName);

                return originalFileName;
            }
            catch (System.Runtime.InteropServices.ExternalException e)
            {
                throw e;
            }
            catch (Exception ex)
            {

                throw ex;
            }
            finally
            {

            }

        }
    }
In the above file I have done the following changes.

  1. I added Windows Azure references to my projects.
  2. I added a AzureConnectionString key to theWeb.Config file with the primary key values of my Azure Storage account.
  3. I created one folder named Photos under the root directory. ( As I need to to show back the uploaded image asynchronously in the view, hence I need to download the blob back to some local folder as image to take it as the source).
  4. Finally I am returning the image name which I am binding in a hidden field present in the view.(On submit of the form data I am saving the hidden field value as the image URL in the database).

Saturday, 22 September 2012

Export Grid to Excel using MVC 3


Below code is helpful for exporting data to excel
 public FileResult ExporttoExcel_Points(SearchCriteria formData)
{
MemoryStream output = ExportFunction_AvailablePoints(formData);

return File(output.ToArray(), //The binary data of the XLS file
"application/vnd.ms-excel", //MIME type of Excel files
"AvailablePoints.xls");
}
// Search criteria is optional
public MemoryStream ExportFunction_Points(SearchCriteria search)
{
// Here we are fetching data using Entity framework
List data = new List();

ReportsRepository repository = new ReportsRepository();
data = repository.GetAvailablePoints(search.AccountNo, search.Name);

MemoryStream output = new MemoryStream();
StreamWriter writer = new StreamWriter(output, Encoding.UTF8);
// The column name shown in the excel file
writer.Write("Account Number");
writer.Write(",");
writer.Write("Name");
writer.Write(",");
writer.WriteLine();

int Count = 0;
foreach (prcGetAvailablePoints_Result re in data)
{
writer.Write(re.Account);
writer.Write(",");
writer.Write(re.Name);
writer.Write(",");
writer.WriteLine();
Count++;
}
writer.Flush();
output.Position = 0;
return output;
}

Tuesday, 29 May 2012

Uploading CSV file using MVC 3 in C#

Here is code for file upload in MVC
public ActionResult ImageUpload(HttpPostedFileBase FileUpload)
         {
              DirectoryInfo dir = new DirectoryInfo(Server.MapPath("~/EventImages"));
              FileInfo[] file = dir.GetFiles();
   
              int x = file.Length;
              x++;
              if (ModelState.IsValid)
              {
                  if (FileUpload.ContentLength > 0 && FileUpload.ContentType == "image/jpeg")
                  {
                      string fileExtention = Path.GetExtension(FileUpload.FileName);
                      string fileName = Convert.ToString(x) + fileExtention;               
                      string path = Path.Combine(Server.MapPath("~/EventImages"), fileName);
                      string dbPath = "~/EventImages/"+ fileName;
                      try
                      {
                          person = new Person();
                          FileUpload.SaveAs(path);
                          
                          dt = ProcessCSV(path);
                          ViewData["Feedback"] = "Upload Complete!";
                      }
                      catch (Exception ex)
                      {
                          ViewData["Feedback"] = ex.Message;
                      }
                  }
              }
          }

private static DataTable ProcessCSV(string fileName)
             {
                 
                 string Feedback = string.Empty;
                 string line = string.Empty;
                 string[] strArray;
                 DataTable dt = new DataTable();
                 DataRow row;
                 
                Regex r = new Regex(",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))");
                
                StreamReader sr = new StreamReader(fileName);
     
                
                line = sr.ReadLine();
                strArray = r.Split(line);
     
                
                Array.ForEach(strArray, s => dt.Columns.Add(new DataColumn()));
     
                
                while ((line = sr.ReadLine()) != null)
                {
                    row = dt.NewRow();
     
                
                    row.ItemArray = r.Split(line);
                    dt.Rows.Add(row);
                }
     sr.Dispose();
     return dt;
     
            }

Friday, 20 April 2012

Sample MVC 3 WebGrid


Some Sample Code for MVC Webgrid
 @{  
   var grid = new WebGrid(Model, canPage: true, canSort: true, rowsPerPage: 5);  
   grid.Pager(WebGridPagerModes.Numeric);  
 }  
 @if (Model != null && Model.Count() > 0)  
 {  
 @grid.GetHtml(tableStyle: "webGrid",  
        columns: grid.Columns(  
             grid.Column("OrderId", header: "Order Id"),  
             grid.Column("PickupDate", header: "Pickup Date "),  
             grid.Column("UserName", header: "Customer Name"),  
             grid.Column("Description", header: "Description"),  
             grid.Column("FromCompanyName", header: "Source", format:  
                   @<text>  
                   @item.FromCompanyName<br />  
                   @item.FromAddress1<br />  
                   @item.FromAddress2  
                   </text>),  
             grid.Column("ToCompanyName", header: "Destination", format: @<text>  
                   @item.ToCompanyName<br />  
                   @item.ToAddress1<br />  
                   @item.ToAddress2  
                   </text>))  
      )  
 }  

Conditionally display an image in webgrid

The following is very useful for those who are playing around with ASP .NET MVC Webgrid controls.

 @grid.GetHtml(  
   displayHeader: false,  
   columns: grid.Columns(  
       grid.Column(format: (item) =>  
         {  
           if (item.IsMainPreview == true)  
           {  
             return Html.Raw(string.Format("<text><img src=\"{0}\" alt=\"Image\"/></text>", Url.Content("~/Content/images/preview-photo.gif")));  
           }  
           else  
           {  
             return Html.Raw(string.Format("<text><img src=\"{0}\" alt=\"Image\"/></text>", Url.Content("~/Content/images/non-preview-photo.gif")));               
           }  
         }  
       ),          
       grid.Column(format: (item) => Html.ActionLink("Remove Photo", "RemovePhoto", "Images", new { photoID = item.Id }, new { @class = "RemovePhoto" }))  
     ));