In this tutorial I am going to show you how you can easily integrate your MVC app with facebook graph API and directly post to user's wall.

This is part 4 of Facebook API integration in ASP.NET series. In order to complete this tutorial, you need to have facebook login button integrated in your app. Please check out Part 1 - Integrating Facebook Login button in ASP.NET MVC 4 application for insturctions on how to do so and working solution that you need for this tutorial.

So, the plan is... - firstly we'll add some helpers for cross domain communication, create facebook wall message model and finally add a controler that will connect all the parts together and talk to facebook server.

Communication infrastructure

Facebook API is no different than any other API service I've come accros so far. For this tutorial, I don't want to use any 3rd party communication plugins for 3 simple reasons:

  1. It won't save us a lot of time
  2. We'll have full control over the code
  3. You'll be able to apply this knowledge and reuse my code for pretty much any other API integration

Let's start from creating MethodResult class. This will be our standard method return object that we'll use troughout this project. Right click on Models folder and select Add -> New Item -> Class. Name it MethodResult.cs. Paste in following code:

namespace FacebookLoginButton.Models
{
    public class MethodResult
    {
        public string errorMessage;
        public ReturnCode returnCode;

        public enum ReturnCode
        {
            Unknown = 0,
            Success = 1,
            Failure
        }
    }
}

We also need some helper methods in our project. Add new Helper.cs file in the root of our app.

Tut 4screen1

and paste in following code:

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using FacebookLoginButton.Models;

namespace FacebookLoginButton
{
    public class Helper
    {
        public static MethodResult SubmitPost(string url, string postValues, out string response)
        {
            MethodResult result = new MethodResult();
            response = string.Empty;

            try
            {
                ASCIIEncoding encoding = new ASCIIEncoding();
                byte[] data = encoding.GetBytes(postValues);

                HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
                webRequest.Method = "POST";
                webRequest.ContentType = "application/x-www-form-urlencoded";
                webRequest.Timeout = System.Threading.Timeout.Infinite;

                webRequest.ContentLength = data.Length;

                Stream requestStream = webRequest.GetRequestStream();
                requestStream.Write(data, 0, data.Length);
                requestStream.Close();
                requestStream.Flush();

                WebResponse webResponse = webRequest.GetResponse();
                StreamReader reader = new StreamReader(webResponse.GetResponseStream());

                var dataReceived = reader.ReadToEnd();

                webResponse.Close();
                reader.Close();
                webRequest.Abort();

                result.returnCode = MethodResult.ReturnCode.Success;
                response = dataReceived;
            }

            catch (Exception ex)
            {
                result.returnCode = MethodResult.ReturnCode.Failure;
                result.errorMessage = ex.Message;
            }

            return result;
        }


        public static string BuildPostString(Dictionary<string, string> postValues)
        {
            StringBuilder sb = new StringBuilder();

            foreach (KeyValuePair<string, string> value in postValues)
            {
                if (sb.Length > 0) sb.Append("&");

                sb.Append(string.Format("{0}={1}", value.Key, value.Value));
            }

            return sb.ToString();
        }
    }
}
 

Helper.cs contains 2 handy methods. SubmitPost makes a post request to given address and BuildPostString builds correct url including all get parameters that we want to pass.

Wall message model

Before we can create our wall message controller, we need the model that will represent message properties. Once we've got that, we'll get Visual Studio to generate controller and input form for us.

Right click on Models folder and select Add -> New Item -> Class and name it WallMessageModel.cs and paste in following code:

namespace FacebookLoginButton.Models
{
    public class WallMessageModel
    {
        public string name { get; set; }
        public string link { get; set; }
        public string caption { get; set; }
        public string description { get; set; }
        public string source { get; set; }
        public string actions { get; set; }
        public string privacy { get; set; }
        public string message { get; set; }
    }
}

Rebuild your solution!

Wall message controller

Now, right click on Controllers folder and select Add -> Controller. Make sure you've got Controller with empty read/wrtite actions selected in Scaffolding options -> Template dropdown as shown below:

Tut 4screen2

VisualStudio will prepopulate our controller with several methods. The only 2 we need are public ActionResult Index() and public ActionResult Create(FormCollection collection). Remove all methods except these 2.

Message form

View() in Index() method should be highlighted in red indicating that there is no view file (.cshtml) associated with this method. Right click on View() and select add view. Now, be carefull, since we're passing an object to it, it needs to be a strongly-typed view. This will make all object properties accessible via @Model variable. Also, we want Visual Studio to generate create form for us, so make sure we've got Create selected in Scaffold template dropdown. Before clicking OK, make sure all properties in the window are set as on following screen:

Tut 4screen3

You can obviously modify the model to make some of its properties required etc and then on form creation Visual Studio will generate neccessary validation login for you.

You'll find html for the form in Views -> WallMessage -> Index.cshtml file. For time being, let's remove all the fields except message leaving following markup:

@model FacebookLoginButton.Models.WallMessageModel

@{
    ViewBag.Title = "Part 4 - Facebook Wall Message";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Part 4 - Facebook Wall Message</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"></script>

@using (Html.BeginForm("Create", "WallMessage")) {
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Create new wall message</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.message)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.message)
            @Html.ValidationMessageFor(model => model.message)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

Now, let's come back to our controller and add some logic to process our request.

Before we do any more coding, we need to install Newtonsoft.Json.dll that will helps us with Json string -> C# object conversion. Below, in article attachments section, there is Newtonsoft.dll download available. Unzip it and drop folder content into /bin folder inside your app. Once you've done that, in Visual Studio, right click References folder, and add reference to Newtonsoft.dll file that you've just dropped into /bin. If you've completed any other of my facebook tutorials (except part 1 - login button), this dlls should already be found in /bin directory.

In WallMessageController.cs file, replace public ActionResult Create(FormCollection collection) method with following code:

[HttpPost]
        public ActionResult Create(WallMessageModel model)
        {
            try
            {
                var postValues = new Dictionary<string, string>();

                // list of available parameters available @ http://developers.facebook.com/docs/reference/api/post
                postValues.Add("access_token", Session["accessToken"].ToString());
                postValues.Add("message", model.message);

                string facebookWallMsgId = string.Empty;
                string response;
                MethodResult header = Helper.SubmitPost(string.Format("https://graph.facebook.com/{0}/feed", Session["uid"].ToString()),
                                                            Helper.BuildPostString(postValues),
                                                            out response);

                if (header.returnCode == MethodResult.ReturnCode.Success)
                {
                    var deserialised =
                        Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(response);
                    facebookWallMsgId = deserialised["id"];
                    return RedirectToAction("CreatedSuccessfully");
                }
                
            }
            catch
            {
               
            }

            return RedirectToAction("WallMessageError");
        }

We also need to add 2 missing actions that we redirect to in the code above. Add following code below Create() method:

public ActionResult CreatedSuccessfully()
{
return View();
}


public ActionResult WallMessageError()
{
return View();
}

Make sure WallMessageController has got all methods and properties as on this screen:

Tut 4screen4

Note that, we are not using facebookWallMsgId variable at all. I added it in case you want to return and present it to user.

Last thing we need to do is to create success and error view. Right click on return View(); statement and add .cshtml views for success/failed attempt notification pages.

Tut 4screen5

Now, rebuild your solution, make sure you dont have any errors on build, press F5 (unless you have it configured as a host), login to facebook using facebook button and go to /WallMessage url. If you've done everything right, you should see following screen:

Tut 4screen6

and when you click Create it should go straiiiiiiiiiight to your facebook wall!

Tut 4screen7

Good luck!

Btw. You may also consider extending session timeout to keep facebook access token in the memory for a little bit longer. Also, it'd be worth to add try/catch login to UserDetails() method in case accessToken variable in nor present in Session object.

Feel free to check out my other facebook tutorials! Aaaand leave a comment if you found it helpful. I love getting comments :)

Tagged: .NET 4  ASP.NET MVC  C#  Facebook Graph Api  Facebook Wall  JSON  MVC 4