Geeks With Blogs
Joe Mayo

Sometimes, the way that LINQ to Twitter materializes queries into entities isn’t immediately clear.  It’s easy to get confused until you see the patterns or make a correlation between the Twitter API results and their representations as LINQ to Twitter entities.  In this post, I’ll explain some of the logic behind the design of LINQ to Twitter entities and demonstrate an example of one of the more oddly designed entity types, Search.

Note: They'll be talking about MVC3 during multiple sessions at Tech-Ed.

Basic Concepts

When designing LINQ to Twitter entities, the fundamental concepts were to have as much parity with Twitter API results as possible and do the minimum amount of customization required to obtain materialized results.  The reasoning weighed heavily towards the ability to match results to the official Twitter API documentation, quicker development, and easier debugging. 

The similarities between class entities and Twitter API XML results are in the areas of object structure and identifiers.  The object structure matches the XML queries as close as possible and identifier names are close to XML element names.  Occasionally, I’ve diverged from Twitter API formats, especially in naming conventions, where I felt the Twitter API element names were much less meaningful.

Note:  A common FAQ is the confusion with ID, UserID, and ScreenName on both the User entity and in the User.Identifier.  The fields on the User entity are input (sent to Twitter), but the User.Identifier fields are output (returned from Twitter).  This design decision was made so that you can see what values were used to compose the query, as opposed to what Twitter returned.  A common scenario is for queries to be made without ID, UserID, or ScreenName because the query is being made on behalf of the authenticated user. This means that ID, UserID, and ScreenName are blank on the entity.  As always, you would read the results of a materialized query from User.Identifier.

The Twitter API results format preference in LINQ to Twitter is XML. This decision comes from the fact that LINQ to Twitter was originally conceived as the example in my book, LINQ Programming/McGraw Hill, of how to build a LINQ provider.  In that case, it was more instructive to use LINQ to XML to translate Twitter API results into objects.  Some Twitter APIs don’t support XML and only JSON or ATOM is an option.  At the time I wrote the Search API, raw XML wasn’t available, but ATOM was.  Being a specialized XML format, I chose ATOM for Search.

Considering the pattern of designing entities as close to the Twitter API results as possible, a legacy of choosing XML first, and Search supporting ATOM, the Search entity models the Twitter API results in ATOM format. Before diving too far into the example, the next section introduces the technology to be used with a couple architectural hints.

Technology/Architecture

A lot of my current work is done with ASP.NET MVC and feedback indicates that this is a very popular Web development option among other developers. I know, I just set myself up for trolls to flame me for my technology choice. Perhaps I should qualify my choice by acknowledging that ASP.NET Web Forms is still a live and viable technology that a lot of people love and like. Anyway, the following example will be in ASP.NET MVC3 with the Razor template engine.

I’ll be moving LINQ to Twitter queries into a Repository.  I could have used LINQ to Twitter in the controllers, but that would have been lazy (I’ll be lazy elsewhere this time). I’ll translate the Search entities into a custom ViewModel.  Hopefully, this will provide a useful example of one option available (there are more) for moving data around your application.

You can get started by creating a new MVC 3 project.  I won’t go into all the details of getting started because there are tons of introductory blog posts and articles across the Web, showing how to start an MVC project. Let’s start with the repository.

Building a Repository

A common practice in application development is to separate concerns so your application is easier to build and maintain. One pattern for separating data management from the rest of the application is called Repository, which this application uses.  Repositories are often used to abstract relational database operations, but are also used for other types of data such as text file, Excel, Web Service, or XML (and more).  For the purposes of this application, Twitter is a data source.  We’ll build the repository to return LINQ to Twitter Search entities, materialized from a query to the Twitter API.  Here’s the repository:

using LinqToTwitter;
using System.Collections.Generic;
using System.Linq;

namespace TwitterSearchMVC.Models
{
    public class SearchRepository
    {
        public List<AtomEntry> Search(string tag)
        {
            using (var twitterCtx = new TwitterContext())
            {
                var searchResults =
                    (from search in twitterCtx.Search
                     where search.Type == SearchType.Search &&
                           search.Hashtag == tag
                     select search)
                    .SingleOrDefault();

                return searchResults.Entries;
            }
        }
    }
}

The code above is just a class, SearchRepository, with a single method, Search, for performing the search.  If you needed more specialized operations with search, you could add more methods, but this is all we need for this demo. The query is a typical search query, using the LINQ to Twitter Type idiom and filtering via a tag. Search queries can filter by any normal or advanced criteria that Twitter offers, but the tag is all we need for the demo.

Now, you have data access code isolated in a repository. We also know that the data will be delivered in the form of a LINQ to Twitter Search entity. Next, let’s look at a similar object, the ViewModel.

Designing a ViewModel

The purpose of the ViewModel is to represent the data that will be displayed in the UI.  One of the first questions you might have is “Why can’t I just bind the LINQ to Twitter Search entity to the UI?”.  After all, demos from many very well-known people bind DB entities to the UI and if they do it then it must be right? Not quite; remember that those are demos in a blog post that are intentionally as short as possible or are trying to demonstrate something and proper architecture isn’t germane to the purpose of their post/article. However, when you’re writing a real-world application, these architectural details, like ViewModels, Repositories, and more become very important.

There are a few reasons why you should use ViewModels, rather than binding data objects; revolving around the shape of the data, display characteristics, and validation.  What you bind to the UI should be a whole different object than what comes from the data source.  First, consider that your UI can have multiple items, including a header, menu, and data display.  The display of the data might be hierarchical or flat.  On the other hand the objects from the data source often have a different shape.  In addition to data shape, you can annotate ViewModel properties with information specific to the UI, like DisplayName.  You can also specify validation rules in your ViewModel that help UI controls manage user input, such as whether a field is required, string length, or email pattern.  All of these ViewModel details are associated with the UI or communicating with UI controls and don’t belong on your data object.  With that in mind, please review the following SearchViewModel:

using System.ComponentModel;

namespace TwitterSearchMVC.Models
{
    public class SearchViewModel
    {
        [DisplayName("Tweet ID")]
        public string ID { get; set; }

        [DisplayName("User Name")]
        public string Source { get; set; }

        [DisplayName("Tweet Text")]
        public string Content { get; set; }
    }
}

The first thing you should notice about the SearchViewModel is that it only has a few properties, as opposed to the multitude of properties available on the Search entity.  This brings up another important issue is that you don’t need to be overloading View processing resources by moving all the data around everywhere. It’s common that you’ll only be displaying a sub-set or specialization of the data returned from a repository.  As I mentioned earlier, you can annotate ViewModel properties to make them work better in the  UI.  In this case, if you were using a 3rd party control like Telerik Grid, the DisplayName attribute would specify the column headings in the grid.

Now that we have data from the data source and a ViewModel for the UI, I’ll show you how to build a controller that translates between the two.

Constructing a Controller

In the controller, I’m going to translate from AtomEntry to SearchViewModel, and display the results. Here’s the controller:

using LinqToTwitter;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using TwitterSearchMVC.Models;

namespace LinqToTwitterSearchMvc.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            List<SearchViewModel> searchVM = PopulateSearchViewModel();
            return View(searchVM);
        }

        public List<SearchViewModel> PopulateSearchViewModel()
        {
            List<AtomEntry> searchList =
                new SearchRepository().Search("LinqToTwitter");

            var searchVM =
                (from search in searchList
                 select new SearchViewModel
                 {
                     ID = search.ID,
                     Source = search.Source,
                     Content = search.Content
                 })
                .ToList();

            return searchVM;
        }
    }
}

Notice that I used a method named PopulateSearchViewModel to get a list of ViewModel objects.  The logic uses a LINQ to Objects query to project the data into a form that can be easily displayed in the view.

Now, let’s look a the view.

Designing a View

As mentioned earlier, I’m using the MVC Razor view engine. I normally use Telerik MVC Extensions, which are a free download via CodePlex.com, but this is just a demo.  So, I went with List scaffolding via the View wizard (you can open the View wizard by right-clicking on View(…) in the controller code and selecting Add View). The example creates a strongly typed View using a List type scaffolding to display results, shown below:

@model IEnumerable<TwitterSearchMVC.Models.SearchViewModel>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
        <th>
            Source
        </th>
        <th>
            Content
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Source)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Content)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
            @Html.ActionLink("Details", "Details", new { id=item.ID }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ID })
        </td>
    </tr>
}

</table>

The UI will show a list of tweets that contain “LinqToTwitter”.  The actual results that are assigned to the Source and Content properties of the SearchViewModel contain HTML anchor tags that you’ll need to parse out yourself.  In many cases, LINQ to  Twitter returns the string data given to it from Twitter.  At other times, LINQ to Twitter will interpret the proper type of data, i.e. int, DateTime, etc., and set the value in the entity properly. You can also set a breakpoint in your code and examine the other fields returned from the LINQ to Twitter query for more information.

Summary

Hopefully, you now understand that there are patterns and reasons for the approach taken by LINQ to Twitter in translating Twitter API results into entities.  I explained some important architectural considerations when building applications, particularly from the ASP.NET MVC perspective. You saw how to take data from LINQ to Twitter entities and translate the data into ViewModel objects for display in the UI.  The result is a quick application that shows you another way to use LINQ to Twitter in an MVC application.

@JoeMayo

Posted on Thursday, April 28, 2011 8:27 AM C# , Twitter , LINQ to Twitter , ASP.NET MVC | Back to top

Copyright © Joe Mayo | Powered by: GeeksWithBlogs.net