Author Archive for JC



22
Jan

The Current State of the Web: Why It’s Pointless to Debate Which Language, Framework or Architecture is the Best

I’d like to make it clear beforehand that the following novel is fully my opinion and not that of my employer.

Whenever I hear a developer address themselves as a “C# developer” or a “Ruby developer” or an “[Insert programming language here] developer” I really can’t help but cringe. Why? Because as an industry, we should be long past the days where you align yourself to a specific programming language. Now, I’m certainly not saying you shouldn’t pick favorites (that’s just human nature), or even lean towards one most of the time (I currently do ~90% C# development), but at the end of the day, being a great developer means learning core fundamentals which can be applied to any language. If you have a solid grasp of object-orientation, functional programming tenets, the benefits of dynamic programming, and so on, you could seamlessly pick up a new programming language that fit one of those paradigms. Most of the time, languages share ideas between each other, so keeping a keen eye to the languages landscape can also help promote fresh concepts regardless which one you’re currently using.

A better question to ask could be: which language paradigm do you prefer? Many developers are very passionate about dynamic programming languages, and so having to use a statically-typed language might feel constraining to them. But, even that debate is getting blurry with languages offering strong type-inference (e.g. F# or Scala) that can get a statically-typed language pretty close to providing a “dynamic” experience. The addition of LINQ into .NET 3.5 also proved that languages that aren’t functional in nature (e.g. C# and VB) can have a strong functional offering. Things like this lead us to believe that the best question to ask here would be: which language paradigms (note the plurality) do you prefer? Single-paradigm languages are a thing of the past, and developers have an even better opportunity to be productive by using a language that amalgamates the paradigms they prefer in a way that is as close to their preference as possible (no language is without its problems).

That said, I’m also not promoting “polyglot programming” here (which I think is mostly a load of crap). What I am saying is that it’s a waste of time to get caught up into a single programming language or even a single paradigm, when that would only be doing yourself a disservice. This is why I also don’t think that a Java vs. Clojure vs. Scala vs. F# vs. Whatever makes any sense either. Sure, each language is going to have tangible benefits and reasons you could argue that it’s better than another, but “better” becomes largely subjective based on your individual scenario and perspective.

For instance, I personally love Clojure and think it’s JVM interop is just beautiful, but would I recommend it to someone who is familiar with Java and is looking for a functional language? No, because the learning curve is too drastic (unless they’re already a Lisp nerd). Scala is just as powerful and provides a substantially lower barrier of entry for someone coming from Java. And it’s type-inference provides plenty of powerful scenarios that make up for it being a statically-typed language. But even that decision is based on my own perspective. Point being: I believe in being prescriptive, but unfortunately you need to do your own research and make your own decision because ultimately the only deciding factor is your own personal situation/preference.

Languages –> Web Frameworks

What does any of that have to do with the current state of the web? Everything. Just like programming languages, there was a time where it was common for developers to align themselves to a specific web framework. If you address yourself as an “Rails developer” or an “ASP.NET developer” or an “[Insert web framework here] developer” you’re doing yourself a disservice. Why? For the exact same reasons mentioned above. I consider myself a developer first and a web developer second. I like to think that I’m a student of all the cross-cutting concepts that make up what it means to develop for the web. Those skills can then easily translate to any framework (and language) you pick.

The real questions to ask isn’t which framework is better but which attributes of a web framework you prefer and make you more productive. Do you like component-driven development (e.g. WebForms, Wicket)? Are you more efficient using an MVC architecture (e.g. Rails, ASP.NET MVC)? Do you fancy a more “light-weight” HTTP framework (e.g. Sinatra, Compojure)? Going further, even those questions have additional sub-questions. There is no “one-size fits all” approach to MVC frameworks for instance, and in some cases the expressiveness of a framework is dependent on a specific language, so you need to pick the one that ultimately suits you best.

Just like languages, some web platforms allow you to be multi-paradigm. For instance, with ASP.NET, you can easily intermingle MVC and WebForms together into a single application. That may or may not be the right option for you, but it’s an option nonetheless. This further drives the point home that arguing WebForms vs. MVC just doesn’t make any sense. Neither Microsoft nor anyone in the community can or should make that decision for you. Why? Because both are equally as good choices, and can ultimately only be chosen based on what makes you and your team more productive.  Point being: I believe in being prescriptive, but unfortunately you need to do your own research and make your own decision because ultimately the only deciding factor is your own personal situation/preference (does anyone else hear an echo?).

If you’d like someone else to make your decisions for you, that is fine as well. Just be clear that that is what you’re doing if you ask an open ended question like WebForms vs. MVC or Ajax vs. Silverlight, etc.

Web Frameworks –> Architectural Styles

So why does the title of this post claim that debates about which language and/or framework is the best is pointless? Frankly, because that debate isn’t interesting anymore, especially in the context of the web. The current state of the web is such that it is the compelling ideas that are interesting and how they affect the way we live our lives. If you want to become the next Twitter (who doesn’t?), you should be focusing your attention on how to add value to the overall social network of applications. From a technical perspective, what makes those types of applications possible isn’t a single language or framework but rather an architectural decision that can maximize on the potential for success. Out of those decisions, new languages and frameworks will be born, that will be founded on solving actual problems rather than just academic exercises.

Am I claiming that you shouldn’t discuss how to make a language or framework better? Of course not. Any given day of the year you will find me discussing everything from MongoDB to Grails to OData and so on. Discussion is absolutely necessary, and it is the continual engagement with the different communities that keep us sharp as developers. But, MongoDB as a product isn’t itself interesting. When it becomes interesting is when MongoDB proves to be a great option for enabling a compelling idea. Hence, talking and debating over whether MongoDB is better than CloudDB or SQL Server is pointless outside of the context of actually creating something meaningful.

When we raise the level of conversation from frameworks and languages to architectural styles, does the debate over which is best become any better? Not really. If we’re talking strictly about web applications, there any number of choices here. RIA (e.g. Silverlight, Flash, JavaFx) vs. Server-centric (e.g. ASP.NET WebForms, Struts 2) vs. “pure” Ajax vs. some hybrid approach vs. Whatever is just as boring a discussion to have as languages and frameworks. Why? Because there is no right answer. The point being is exactly the same for architectural decisions as I’ve already stated twice. The best thing we can do as developers is strive to stay as relevant as possible in all areas of our industry. Am I saying you should become a jack of all trades and a master of none? Certainly not, but there is a healthy balance between betting your career on a specific technology and positioning yourself to move forward with the industry as a whole. Let’s take a look at Twitter, and see how they’ve done this beautifully.

Twitter Case Study

If I was to ask you what makes Twitter so successful from a technical perspective, what would you say? Would you talk about its use of Scala for the backend or Rails for the front-end? What about its extensive use of memcached and their rather genius caching strategy? While all of that definitely peaks my nerdometer, it doesn’t have anything to do with why they’re successful. I’d argue that what makes them successful is also what makes the debate over what language, framework, or UI technology the best is pointless: their API.

Let me ask two other questions here:

  1. Is Twitter a web site? A web application? A web service?
  2. What is your favorite Twitter client? The website? Seesmic? Tweetdeck? Tweety 2?

Answering #1 would depend entirely on how you view Twitter. You could say that it is a web site, and yes www.twitter.com does exist, but I’d call that their “canonical UI”. What I mean by that is that the website is nothing more than the default client that anyone new to Twitter might use. It is the baseline experience that Twitter personally created to make sure that anyone could access their service. Ultimately though, Twitter’s value is wrapped up in their services and ultimately their data (including users and tweets).

The answer to #1 leads directly into #2. Because Twitter isn’t just a website, and because they’re not partial to who uses their data, that allows us to actually choose a favorite client. Even further, we might have a favorite client for different platforms (e.g. Windows Mobiles, iPhone, Android, Mac). Because of the way that Twitter positioned themselves, they’ve enabled every user on every platform to choose the experience they prefer. That’s a very powerful achievement, and is exactly why it no longer makes sense to argue over what UI or web framework is the best. If you want to achieve large success, it isn’t in the client business, it’s in the services and data business. Whoever has the data has the power.

This is also why it doesn’t make sense to ask whether it’s better to use Scala on the JVM for Android or jQuery and ASP.NET or Flash and ActionScript, etc. I don’t know about you but I’d rather come up with a great idea and then make my data portable so that any of those aforementioned experience would be possible. That’s when your reach and social relevance can be truly compelling. This is also the blueprint being employed by just about every startup worth anything (e.g. Foursquare, BlockChalk). Languages, frameworks, and architectural styles are nothing more than tools in our arsenal that can enable us to create our ideas. We’ll continue creating new ones, and there will continue to never be a right answer in any of the categories.

The discussion over services and data opens a whole other can of worms that I’m not going to go into in this post. Maybe another day :)

Have The Conversations

What can you do to contribute to the overall conversation of the web? Be open-minded and be solution-driven. If you need to ask a question about product comparisons, make sure to have some solution context to back it up, so that recommendations can be made based on merit and not pointless debates over which is “better”. Also, be willing to hear people out when they’re talking about some language, framework or style. Good ideas come from all directions, and you can guarantee that what you believe in today will be obsolete tomorrow (not literally, but it almost feels that way sometimes).

Cross-pollinated conferences like CodeMash and MIX are the perfect place for such conversations to occur. When the Ruby folk and Java peeps and .NET group and PHP clan (etc.) get together magic happens. If you see me at one such event, I’d love to chat about what cool stuff you’re doing. Otherwise, if you’re at a conference, talking about cool stuff, hopefully I’ll find you :)

17
Nov

Tailspin Travel

logo.pngThis morning, Cameron Skinner presented a demo in Bob Muglia’s keynote at the PDC. The demo focused on some of the most exciting new features coming in Visual Studio 2010, .NET Framework 4, SQL Server 2008 R2, and the new Windows Server AppFabric. We felt that the demo did a great job of highlighting the value of the next wave of Microsoft developer tools and as such we wanted to make sure that it was readily available to everyone.You can now download the Tailspin Travel application from Codeplex (download here). In addition to the feature use cases that were presented in the demo, the released version of Tailspin contains many additional scenarios to help developers see a broader view of possibilities with the respective technologies.

Technologies Covered

The Tailspin Travel application covers a pretty substantial set of functionality, but ultimately seeks to provide a holistic perspective of how Visual Studio 2010, .NET Framework 4, and the server platform can be used together. The following is a list of the exact features that are shown in the application:

Visual Studio 2010
  1. Assembly Dependency Graph
  2. Multi-monitor
  3. Navigate To dialogue
  4. IntelliTrace
  5. New WF designer
  6. MSDeploy
  7. Coded-UI tests
.NET Framework 4
  1. ASP.NET MVC 2
  2. Windows Identity Foundation
  3. Windows Workflow Foundation
  4. Windows Communication Foundation
  5. Entity Framework
Server Platform
  1. Windows Server AppFabric
    1. Service Container
    2. Workflow Container
    3. Monitoring
    4. Cache
  2. SQL Server 2008 R2
    1. DAC

System Requirements

Tailspin was built using Visual Studio 2010 Ultimate, and there are a few features in use in the demo that require that version (e.g. coded-UI tests). If you’re using a different SKU, you’ll still be able to run the solution, but there will be some features you won’t be able to take advantage of.Because we consider the new Windows Server AppFabric a key part to the Tailspin Travel application, we also require that you have it installed. This is what enables the memory-caching, as well as the service/workflow containers, and monitoring support.SQL Server 2008 R2 isn’t a hard requirement, but if you don’t have it installed you won’t be able to deploy the Data-Tier Application (DAC).

Next Steps

We plan on doing at least a couple more iterations on Tailspin Travel. There are a few tweaks we’d like to make, plus I’m confident we’ll get some great feedback from you guys that will help make it even better.

20
Jun

How the DataContext can change your data and your life (well, sort of, but not really)…

In the previous post I explained how the DataContext can be used for read-only scenarios, both in a standalone fashion and in conjunction with a DataView. I explained how the additional level of abstraction over an underlying service proxy can be beneficial, but ultimately alluded to the fact that the DataContext’s true power lies in its unit of work behavior that can be achieved pretty trivially. In this post I want to dig into how the change tracking and data persistence functionality of the DataContext works.

Let’s pick up where we left off in the previous post. We had an ASMX service already in place for returning customer data. Using ASP.NET AJAX 4 we could create a DataContext that pointed at the service and associate it with a DataView to dynamically display all customers returned from the service. One thing that we didn’t mention is the DataContext’s saveOperation property. We could modify our previous example like so…

var dataContext = $create(Sys.Data.DataContext, { 
                               serviceUri: "Customers.asmx", 
                               saveOperation: "SaveCustomers" 
                          });       
 
var customersTemplate = $create(Sys.UI.DataView, { 
                            autoFetch: true, 
                            dataProvider: dataContext, 
                            fetchOperation: "GetCustomers", 
                            fetchParameters: { count: 10 } 
                        }, 
                        null, 
                        null, 
                        $get("customers-template"));

Notice that nothing has changed from the perspective of the DataView declaration. The only difference between the above sample and the read-only scenario we created in the previous post is the existence of the saveOperation property on the DataContext. Here we’re telling the DataContext that there is a method called “SaveCustomers” on our ASMX service that is responsible for handling the persistence of changes. When we call the saveChanges method on the DataContext, it will trigger a request to the save operation method, passing it a change set that represents all of the changes made to the local data since the last time it was saved.

Two questions arise here that need to be addressed before moving on:

  1. How is it that changes are happening to the data coming back from the DataContext?
  2. How is it that the DataContext can know which exact changes have happened when trying to persist them back to the server?

Remember in the previous post that I mentioned that the DataContext was basically a class that can connect to a server-side resource, as long as that resource serves JSON data? That technically isn’t true, since the DataContext could work just fine with services that return XML or other payload formats. The reason I limited the DataContext’s abilities is because the only type of data that it can provide change tracking on is JSON data, and since change tracking is the key feature of the DataContext, it should almost be viewed as a limitation.

The main value of services that return JSON data is that once that data is returned to the JavaScript client it can immediately begin using it since that data is represented by instances of objects, as opposed to XML that would need to be parsed. To answer the first question above, since the DataContext is retrieving JSON data from services, and JSON data is simply object instances in memory, changes can happen to the data as easily as modifying property values on the returned objects. But, if your using a DataContext simply to associate it with a DataView (or some other control), you’re not necessarily handling the returned data yourself, but rather, the DataView is. Let’s take a brief detour into client templates…

In all of the samples that I’ve been using thus far I’ve instantiated a DataView around an element called “customers-template”. What exactly is “customers-template”? It is an instance of a client template (another new feature in ASP.NET AJAX 4) that is responsible for displaying instances of customers. The customers client template, in our example, looks like this…

<table cellspacing="0">
    <thead>
        <tr>
            <th>Title</th>
            <th>First Name</th>
            <th>Middle Name</th>
            <th>Last Name</th>
            <th>Suffix</th>
        </tr>
    </thead>
    <tbody id="customers-template" class="sys-template">
        <tr>
            <td><input type="text" value="{binding Title}" /></td>
            <td><input type="text" value="{binding FirstName}" /></td>
            <td><input type="text" value="{binding MiddleName}" /></td>
            <td><input type="text" value="{binding LastName}" /></td>
            <td><input type="text" value="{binding Suffix}" /></td>
        </tr>
    </tbody>
</table>

What we have here is a template that represents a tabular display of customers, including the full name, title, and suffix. The part that represents the actual client template is the <tbody> element. Notice that the ID of the <tbody> corresponds to the ID of the element that is represented by the DataView control we created. What the DataView will do is ask its corresponding DataContext for data (which will call its respective service), instantiate an instance of its associated client template, and create an instance of the template for every instance of data that is retrieved from the DataContext. Hence, in our example, we will get a table row for every customer.

In order to actually interpolate data into the client template you use what are called bindings. ASP.NET AJAX’s bindings look very similar to those in WPF/SL, and are represented by the contents of the value attributes of the <input> elements in the example above. Bindings are a fairly complex topic that I won’t get into it this post, but for the sake of our sample you can think of bindings as being able to synchronize two property’s values together. In this case, we’re synchronizing the value property of the textboxes to individual properties of the customer objects (remember that we’re getting back JSON data, which includes properties for all of the customer’s assets).

If we were to run this sample as is right now, we’d get something like this (I have some basic CSS in place as well)…

image

As expected, we have a table with a row for each customer, and the customer’s name, title, and suffix are bound to individual textboxes. This is great for read-only scenarios so far, but since we’re using textboxes for this display, it would be great to be able to edit the customer data and push it back to the server. Because we used bindings to attach the textbox values to customer properties, when you modify the value of any of the textboxes in this table you’re also modifying the value of its respective customer object. This is a very subtle but very powerful feature of client templates and bindings. This also answers our question of how you can go about changing your data when using it in conjunction with a DataContext and DataView.

Let’s move on to the second question of how it is the DataContext can know about the changes. The act of binding data to controls is by no means anything new. Binding a customer to a row, and then each of its properties to textboxes is a pretty basic act. But, what we really need, is for each of the individual customer instances to be able to report back to their “parent” DataContext when they’ve changed. If I go up into the form above and enter “Sr.” into the Suffix textbox for Orlando Gee, I need that customer instance that represents Orlando Gee to notify the DataContext that he has changed. That way, whenever I call the DataContext’s saveChanges method, it would already know what changes have happened and can send them to the service.

If you were using WPF or WinForms or Silverlight, you would have to make your Customer class implement an interface called INotifyPropertyChanged. The whole purpose of this interface is to make objects capable of notifying some interested party when it has changed. This approach works alright but it is also painful and is frankly a gleaming example of the constraints of statically typed languages. JavaScript is a dynamic language and as such we shouldn’t be held down by such limitations. But the need still exists to have our customer objects report their changes back to the DataContext. How will that happen?

Attention: this entire paragraph is very key…whenever the DataContext is used to retrieve data from a service, it will automatically inject every JSON instance with the necessary logic so that it can report any changes back to the DataContext. The above example would flow something like this…

  1. The DataView asks its associated DataContext for data
  2. The DataContext requests its associated service for the data, and once retrieved injects the objects with change tracking behavior
  3. The DataView then creates an instance of its associated client template for every instance of data it received from its DataContext and binds the data instance to the client template instance
  4. If you modify data through the client template UI (i.e. a textbox), since the JSON object instance is bound to the UI, and the JSON objects contain change tracking logic, those changes will trigger a notification to the DataContext letting it know all of the changes
  5. When you call DataContext.saveChanges, it already knows about every change that has happened (by virtue of the binding notifications), and can simply send that change set to the service
  6. The DataContext will then call the service method specified in the “saveOperation” property, passing the change set

What this means is that you don’t have to worry about change tracking or data synchronization at all,  which is great because those are two of the most painful parts of developing data-driven applications (in my opinion). On the service-side you simply need to create the corresponding method to receive the save operation. For our ASMX service it could look like this…

[WebMethod] 
public void SaveCustomers(List<Change<Customer>>> changeSet) 
{ 
    // Save the customer data 
}

The Change class is a simple container class that wraps the data instance that was changed and the change that occured (e.g. Insert, Update, Delete). Within that service method we can now take the appropriate actions to persist the changes based on whatever our data store is.

While ASMX and WCF provide a great option for general-purpose services, if what you need is a service for the sole purpose of retrieving and persisting data then using either ASMX or WCF is a roundabout way to go. ADO.NET Data Services should be seen as the defacto option for data-centric services since it does most of the heavy lifting for you. In fact, if you’re using a DataContext with a DataView and a Data Service (that’s a lot of data stuff) then you don’t have to do anything extra in order to persist your changes. Data Services automatically includes the logic to receive a change set and push it back to your data store, which alleviates the need to create a save operation.

So what is the moral of the story? The DataContext class can be used for read-only service interaction, but truly shines when you need automatic change tracking and unit of work behavior. You can use the base DataContext class when working with an RPC-style service (i.e. ASMX/WCF), but in most cases, if you’re developing a data-centric application, using the AdoNetDataContext along with an ADO.NET Data Service is going to provide you with a much easier solution. The DataContext works beautifully with a DataView and allows you to create dynamic data-driven UI, that when used with live bindings, can provide a really compelling user experience.

There is though still an outstanding question here: what if you’re using ASP.NET MVC and you want to leverage controllers to handle all incoming requests? There are plenty of scenarios where you don’t want to have to create an ASMX/WCF/Data service just to provide data to an AJAX client, when your controllers are perfectly good for that (in fact you could argue that in a “true” MVC application, the whole point of the controller role is to intercept user interaction, so using another service type is slightly awkward). Remember in the last post how I mentioned that the DataContext was also a great foundation for creating more specific context’s for additional scenarios? In the next post I’ll show how we created a DataContext that provides full change tracking and persistence when using ASP.NET MVC.

19
Jun

Gaining some context into ASP.NET AJAX 4’s DataContext…

The ASP.NET AJAX 4 release has some really cool features in it that can help lower the barrier of entry into developing client-side web applications (jQuery doesn’t hurt either). One of the more compelling new classes is the DataContext. Basically, the DataContext is an object that is capable of consuming a server-side resource that serves JSON data. In its most basic form, you simply give it the URI of a service and the operation name to execute and it handles making the underlying request. If you had an AJAX-enabled ASMX service like so (note: I’m using the Entity Framework)…

[ScriptService] 
public class CustomersAsmx : WebService { 
    private CustomersContext context = new CustomersContext(); 
 
    [WebMethod] 
    public Customer[] GetCustomers(int count) { 
        var customers = (from cus in context.Customers 
                         orderby cus.Id 
                         select cus) 
                         .Take(count) 
                         .ToArray(); 
 
        return customers; 
    } 
}

Calling that service using a DataContext might looking something like this…

var context = $create(Sys.Data.DataContext, { serviceUri: "Customers.svc" }); 
context.fetchData("GetCustomers", // Operation name 
                  { count: 10 }, // Operation parameters 
                  Sys.Data.MergeOption.overwriteChanges, // Merge-option (optional) 
                  "POST", // HTTP verb (optional) 
                  function customerFetchSuccess(customers) { 
                      // Do something with customers... 
                  }, 
                  function customerFetchFailure(error) { 
                      // Handle the error somehow... 
                  });

As you can see, there are all kinds of options that can be passed to the fetchData method, many of which are optional. The above scenario makes use of an ASMX service, but you could just as easily be targeting an AJAX-enabled WCF service, which both have pretty similar semantics in this scenario.

What if you’re using ADO.NET Data Services though? In theory, since the DataContext class can make requests against any service that responds with JSON data (which Data Services can do), it should be able to consume a Data Service with a few modifications to the above code sample…

var context = $create(Sys.Data.DataContext, { serviceUri: "Customers.svc" }); 
context.fetchData("Customers", 
                 { $top: 10 }, 
                  null, // Defaults to overwrite changes 
                  "GET", 
                  function customerFetchSuccess(customers) { 
                      // Do something with customers... 
                  }, 
                  function customerFetchFailure(error) { 
                      // Handle the error somehow... 
                  });

Obviously the serviceUri property now points at a Data Service instead of an ASMX/WCF service, but the real points of interest lie in the operation/parameters. While ASMX and WCF are traditionally operation-centric services (see note below), ADO.NET Data Services is resource-centric, and doesn’t have methods that we can target (unless of course you’re using service operations). Hence, to consume the Data Service from our DataContext, we set the operation method to the name of the resource set (i.e. Customers) that we want to retrieve. Operation parameters work the same as with ASMX/WCF, but since Data Services has its own predefined set of query options, we simply need to comply with them (i.e. using $top). Finally, Data Services uses the GET HTTP verb for all data read requests (as opposed to traditional RPC style services that use POST for everything), so we need to set that.

By default, WCF leans towards the edge of RPC-style/SOAP services, but is capable of providing REST-style services that are resource-oriented. An ADO.NET Data Service is itself a WCF service that exposes a RESTful interface and makes data-centric services really easy to implement and consume.

If you ran the above sample, it would work, but not exactly as you might like. The customers data that is passed into the success callback would be a string of XML, representing the AtomPub feed sent back from the Data Service. The reason for this is because ADO.NET Data Services will by default serve its data as AtomPub. If a request comes in that includes the Accept HTTP header set to “application/json” then the Data Service will return JSON data. Unfortunately the DataContext class doesn’t set the Accept header when making service calls, which makes consuming a Data Services from it pretty sub-optimal.

You might be thinking to yourself: “Hey that’s cool, I’ll just grab the request that is associated with the DataContext and add the Accept header myself!”. Unfortunately that isn’t possible since the DataContext doesn’t expose its underlying request. If you’re a seriously hardcore ASP.NET AJAX dev, you might be thinking: “Alright fine, I’ll just use the WebRequestManager to tap into the request before it’s sent”. That is totally possible, and would look something like this…

Sys.Net.WebRequestManager.add_invokingRequest(function(sender, args) { 
    var request = args.get_webRequest(); 
    request.get_headers()["Accept"] = "application/json"; 
});

Unfortunately that solution is ridiculously unintuitive and is now intercepting all requests just to accommodate a single case. Unless you have a really good reason you should almost never do this. How then can we use a DataContext to easily consume a Data Service? Well, you can’t use the DataContext per se, but you can use a subclass of it, like so…

var context = $create(Sys.Data.AdoNetDataContext, { serviceUri: "Customers.svc" }); 
context.fetchData("Customers", 
                 { $top: 10 }, 
                  null, // Defaults to overwrite changes 
                  null, // Defaults to GET 
                  function customerFetchSuccess(customers) { 
                      // Do something with customers... 
                  }, 
                  function customerFetchFailure(error) { 
                      // Handle the error somehow... 
                  });

Notice that we’re now using an AdoNetDataContext instead of the vanilla DataContext. This immediately does two interesting things for us: defaults the HTTP verb to GET (as opposed to POST), and sets the Accept header to “application/json” for us (so the Data Service will return JSON data instead of XML). Now if we ran the above code, we would successfully get back the top ten customers as JSON objects.

The DataContext class should be viewed as two things:

  1. An easy solution for consuming RPC-style services (i.e. ASMX or WCF)
  2. A great foundation for other higher-level service clients

If your server-side resource is an ASMX or WCF service then the basic DataContext is exactly what you want and will work seamlessly. If however you’re using an ADO.NET Data Service, then the DataContext lacks the semantics you need to work successfully, and you should use the AdoNetDataContext instead. If you want to consume some other service type that requires some special attention, you could also choose to subclass DataContext and add on the extra behavior you need (it honestly is pretty simple to do).

Hopefully some of you are reading this and thinking that I’m absolutely crazy to think you would use a DataContext just to retrieve data. The above code sample for consuming an ASMX service could be achieved using a class that has been in ASP.NET AJAX since its conception (WebServiceProxy), and doesn’t require us to create an instance (um, because it’s “static”)…

Sys.Net.WebServiceProxy.invoke("Customers.asmx", // Service URI 
                               "GetCustomers", // Operation name 
                               false, // Use GET 
                               { count: 10 }, // Parameters 
                               function customerFetchSuccess(customers) { 
                                  // Do something with customers... 
                               }, 
                               function customerFetchFailure(error) { 
                                  // Handle the error somehow... 
                               });

Notice that this code is nearly identical to what we wrote when using the DataContext, but we’ve removed the need to $create anything. There also happens to be an AdoNetServiceProxy class as well that enables you to make service calls to a Data Service, similarly to how we achieved it above. So the question arises: why on earth would you ever use a DataContext vs. just using its respective service proxy? There are two reasons:

  1. You need an abstraction over your underlying request/proxy type
  2. You need unit of work behavior, complete with automatic change tracking

The first part is important because the WebServiceProxy and AdoNetServiceProxy are drastically different and don’t share a common base class (er prototype). This becomes problematic when you have other classes that need to consume data, but don’t want to be tied to a specific service type. A great example of this is the new DataView class, which allows you to create dynamically-templated UI. The DataView has a property called “dataProvider” that accepts a DataContext, and uses that context to handle populating its templates with the data it needs. We can now hand the DataView any DataContext subtype we want and it will be able to consume the data without a care in the world…

var dataContext = $create(Sys.Data.AdoNetDataContext, { serviceUri: "Customers.svc" }); 
var customersTemplate = $create(Sys.UI.DataView, { 
                            autoFetch: true, 
                            dataProvider: dataContext, 
                            fetchOperation: "Customers", 
                            fetchParameters: { $top: 20 } 
                        }, 
                        null, 
                        null, 
                        $get("customers-template"));

I’ll save the gritty details of the DataView for another post. One point of interest though is that because we’re no longer manually calling DataContext.fetchData (because the DataView is doing that for us), the operation and parameters properties are now set on the DataView instead of the DataContext. This scenario is probably the most common usage of the DataContext, and illustrates how simple using a DataContext can be.

The second point made above was slipped covertly under the radar, but really should have been highlighted as being the major reason of why you would ever use a DataContext in the first place. The abstraction is nice but isn’t nearly compelling enough to warrant introducing an entirely new concept into your life. The DataContext is valuable because it provides you a unit of work experience. Up to this point I’ve purposely shown it being used for read-only scenarios, but it is so much more.

If you are looking to simply retrieve data from a service, you should use one of the proxy types (i.e. WebServiceProxy or AdoNetServiceProxy). In fact I would go so far as to say that if you find yourself manually calling the DataContext’s fetchData method, you are probably doing something wrong. If however you need to change the retrieved data, and then persist those changes back to the server, a DataContext is your best friend.

What if I told you that the code samples above that used a DataContext with a DataView will automatically provide change tracking and can save any changes back to the server as easy as a single line of code…

dataContext.saveChanges();

What subtleties exist with change tracking/persistence when working with DataContexts of different types? How exactly could such rich functionality be achieved with a single line of code? I’ll cover that aspect of the DataContext in another post…

01
Apr

Announcing .NET Framework 4.0 Sentient DSLs

As of today, we’re officially unveiling a brand new feature coming with Visual Studio 2010 and the .NET Framework 4.0: sentient DSLs. If you’ve become intrigued with all the hype around leveraging domain-specific languages, but you’re concerned about the added complexity that comes with having to learn a bunch of different grammars, then sentient DSLs are for you. Write the code that you think makes sense, and allow the application to create itself. Coding should be fun, and most importantly, it should be easy.

Check out this new feature in action over at Channel 9: http://channel9.msdn.com/shows/10-4/10-4-Episode-14-Sentient-DSLs/. As always, I’d love to get your feedback on how useful you think this could be to you.




July 2010
S M T W T F S
« Jun    
 123
45678910
11121314151617
18192021222324
25262728293031

Categories