.NET RIA Services: From Vision to Architecture

A deep drilldown into the thinking behind .NET RIA Services, the concepts and architecture behind the bits...

.NET RIA Services is now public. And folks at MIX generally loved what we're doing in this space, which is a promising start. We don't yet have a great landing page for the technology but here is what the download page currently has to say:

Microsoft .NET RIA Services simplifies the traditional n-tier application pattern by bringing together the ASP.NET and Silverlight platforms. RIA Services provides a pattern to write application logic that runs on the mid-tier and controls access to data for queries, changes and custom operations. It also provides end-to-end support for common tasks such as data validation, authentication and roles by integrating with Silverlight components on the client and ASP.NET on the mid-tier.
A rather brief summary. There is also a walkthrough I recommend checking out to get a first hand feel at the basic usage. In this post, I want to share some of the thoughts and architectural concepts behind the bits. This is going to turn into a super long post, but I hope it is still a useful read, and provides insight to both evaluate and hopefully appreciate the bits.

As we looked at Silverlight planning, we realized RIA development is simply hard. There are too many moving pieces to manually stitch together between the client and the server. There are too many things that are un-natural, yet the norm, starting with the forced n-tier (many developers are used to writing 2-tier apps), async (when sync is the norm), dealing with latency (doing so incorrectly has the potential to break end-user experience), figuring out how to be less chatty, dealing with validation, conflicts, disconnected or occasionally connected scenarios, performing authentication and sharing user state across client and server, the list goes on and on...

We wanted to simplify RIA development... and bring back productivity for mainstream development, in much the same way that ASP.NET 1.0 provided client app developers a productive platform for developing Web apps. The pendulum has swung, and it is time to simplify RIA-style client development.

For many reasons, I like to think of .NET RIA Services and what we are doing as RAD for RIA.

Seeing RIAs in a New Light

The biggest value proposition that .NET RIA Services brings to the table is a new unified look at the client and server as two halves of the same logical application. The two halves aren't two separate applications. Simply speaking, we wanted to make development as simple as 2-tier apps, without sacrificing good n-tier design or compromising on fundamentals.

Lets look at the anatomy of a classic Web application (and most Ajax apps aren't significantly different).

Classic Web Application

The web application on the middle tier talks to one or more back-end databases and services. It contains a data model and data access layer defining what the app works over, application logic that constrains what can be done using the application and finally some presentation logic, typically something that projects HTML for rendering in a browser. Most of the app resides on the server, and that simplifies things; accessing different bits of functionality is as simple as vanilla method calls.

With a RIA, most of the presentation logic moves to the client to improve the UX and to make effective use of local state. The result is additional work for the developer: defining a full-fledged services layer, new types and contracts to share etc. and continually evolving them as the app evolves on either end.

We see a subtly different picture - a broader single box called the Rich Internet Application. A RIA isn't just a client app, but an "Internet" app that includes a server component.

Rich Internet Application

The presentation tier is separated by a network, but .NET RIA Services steps in to provide the plumbing behind the scenes to preserve a 2-tier feel to the overall codebase. Peel back a layer, and underneath the covers, you'll see familiar building blocks: the goodness of services, and open/standard protocols (more on that below). They're simply implementation detail, that you don't have to focus on as the high order bit. Instead you get to focus on your application's logic and user interface.

When you look at the complete picture that includes other applications that version and evolve independently, concrete services with well-thought out and explicit contracts are still very much recommended. That doesn't change with .NET RIA Services.

The network in between the client and server is still very much real. Our goal isn't to hide that with some magic. However we want to address that trust boundary and point of latency by incorporating those factors into the programming model and making them natural, and simplifying the associated tooling.

What this fresh look at RIA lets us do:

  • Share behavior, application semantics, metadata, and even implementation rather than just contract between tiers. Its all within the bounds of the same app. Why do things twice?
  • Gear our tooling to address what you're building - a RIA. There is a lot more we have to do to get to nirvana here. Over time...


A Concrete, End-to-End, Application Pattern

I should preface this section by saying that there isn't a single valid pattern. Lots of folks think there is only one pattern that works. I think otherwise. And consequently what we have here will work for some applications, not all. We do have lots of extensibility hooks for those wishing to extend the pattern or apply it to their specific scenarios and perspectives.

The end-to-end application pattern revolves around data and domain-specific logic. What is interesting is we're making what a lot of application developers already do more concrete, rather than leaving it as an exercise for developers, so that it can be tooled and made more mainstream.

Using the example from my MIX demo, I have a simple data model with Product and Category entities.

DomainService + DomainContext Pattern

The first part of our pattern is to write a DomainService class. This represents your application domain, your application logic, or business logic. It surfaces the set of data a client can see, which might be DAL types, or projection types invented specifically for use by the presentation tier, or a combination thereof. It also surfaces a set of operations: both CRUD-based and custom domain-specific operations. It also specifies rules around the data and the operations such as authorization and validation. Finally it encapsulates any DAL-specific nuances. A DomainService is optimized to be stateless - to respond to query requests and to change set processing requests.

The second part of the pattern is what we generate - the client-side data model - in a DomainContext class. This class represents the view of what the client can see. It contains lists of objects, one for each type exposed to the client, and it contains a set of load methods that roughly correspond to the queries exposed on the service. These load methods can be used to load objects into the corresponding lists. The individual objects and lists track changes and raise change notifications. The DomainContext can extract all the changes, create a change set and submit it to the service for processing and commiting. A DomainContext is optimized for taking advantage of the stateful environment and to be a well-behaved citizen in a binding-centric presentation technology such as Silverlight or WPF.

When you peel a layer, you'll see that the infrastructure is built on familiar building blocks of services and proxies and deriving the qualities of service-based design.

Infrastructure behind a DomainService and DomainContext

The only difference is since you're within the bounds of within an application, the infrastructure is closer to plumbing that is provided through tooling and runtime framework functionality. Specifically the DataService on the server is an honest to goodness HTTP endpoint speaking either REST or SOAP, using either XML or JSON (implemented in the longer term via WCF and ADO.NET Data Services). On the client, the DomainContext serves as a specialized proxy that is aware of the underlying data semantics.


A Scalable Pattern

The DomainService pattern for writing your application logic itself isn't restricted to just RIAs written in Silverlight connecting to some back-end relational database. That is a single slice of a bigger story.

DomainService + DomainContext Pattern Scale Out

The DomainService pattern can work against a variety of data sources from plain old CLR types, that might be manufactured from thin air, retrieved from cloud storage, such as Azure, or retrieved from a database, but through a repository layer. In the bits we released, we support Linq To Sql and Linq To Entities. In my demos, I showed Azure and CLR types. We plan to share more details on how to work with a greater variety of back-end data access technologies.

On the other side, we have Silverlight and WPF representing a .NET to .NET slice of the story. However, the infrastructure on top of DomainService speaks in an open/standard/RESTful manner. As such script/Ajax clients using any Ajax framework can work with the middle tier. Server-side rendering-based applications using Web Forms or MVC can make use of the same application logic. And finally, for non-UI clients, such as other applications, one can build a services layer to project the data and operations via a SOAP or REST interface. My MIX demo bits contain a sample of Ajax and ASP.NET usages.

The DomainService you build is a concrete and tangible asset in your overall application that can be reused and be a central point for abstracting your data layer from the rest of the system. As such it might be interesting to ensure high quality and maintainability through a set of unit tests. In fact, a unit test is simply another client of the application logic. My MIX demo bits contained a sample of that.


A Pattern Beyond CRUD

Application Services and Patterns behyond CRUDThe final piece about this pattern I want to cover in this already long article is how this ties in with our application services story, and how they address concrete application scenarios while building on this foundation of DomainService+DomainContext and CRUD. These application services will ratchet up the productivity level one more notch, by providing out-of-the-box solutions for common tasks and scenarios, while being extensible and pluggable thanks to the underlying foundation.

Lets look at the one application service we ship out of the box - Authentication. Specifically this takes care of logging in, enabling role-based authorization and managing user settings. And it does so on both the server and the client - remember, single application, single set of patterns that apply on both tiers. Authentication derives from DomainService. The entity or data it exposes is a User object. In addition to getting the current user, it exposes operations such as Login and Logout. However the API that authentication itself exposes doesn't have a CRUD feel. Instead it looks like a specific API tailored for the specific scenario of authentication.

In similar vein, we might see other application services such as UserRegistration, Diagnostics, Analytics, ApplicationWhiteboard etc. Each offers a domain-specific API, but would build on the foundation of DomainService+DomainContext and CRUD.


Summary

Despite being prescriptive, I think we have a very flexible technology built on building blocks that can be replaced. A small set of examples:

  • For example, you could write your own explicit service on top of the application logic or DomainService pattern, and you could create an explicit service reference in your client, if you prefer to be explicit across tiers, rather than using all of the underlying infrastructure.
  • You could plug in your own back-end store if the ones we support out-of-the box don't match your needs. For example, you could plug in a rich domain model.
  • You could decide how much of the DAL you want to expose or how little, by instead constructing an explicit set of presentation types.

We still have a ways to go. In many ways what was shown is just the first step. There are still missing pieces, and new areas we need to tackle. This is where you come in - with your feedback upon evaluating the technology further.

Posted on Friday, 3/20/2009 @ 2:08 PM | #Silverlight


Comments

60 comments have been posted.

Adam Wolf

Posted on 3/20/2009 @ 8:04 PM
Great talk at Mix . I just watched it on line.

Thanks for the demo code, and keep up the awesome work.

Adam

Phil Cockfield

Posted on 3/20/2009 @ 10:05 PM
Nikhil, I gotta say this is one of the most exciting things I've seen in a long time. This is a really beautiful design you've come up with, that hits straight at a central set of mucky problems. Thank you so much.

One question, you talk about the plugability, and certainly what I've played with so far has been really great (basically, creating my own domain model, and exposing it via [DomainService]). I wonder, with the Authentication piece; will we be able to plug in outside authentication providers, namely OpenID - or are we locked into the ASP.NET / Windows providers?

Thanks!

Nikhil Kothari

Posted on 3/20/2009 @ 10:11 PM
@Phil - Thanks.

The plan is very much to have the client-side extensibility to plug in things like OpenID. However this is locked down for the initial CTP. It is a key scenario, and I know we need to think through the client API and open it up.

Before we open up Authentication too broadly, we wanted to do a couple of things: a) ensure we have the right model to plug in things like OpenID (didn't want to prematurely open it, but have it not set up to work for immediate scenarios), and b) ensure we're demonstrating the right model and precedent for other app services to come.

Julius Ganns

Posted on 3/21/2009 @ 12:46 AM
Hi Nikhil,

unfortunately I wasn't able to attend Mix this year, but after reading your posts and documents about .NET RIA Services, I really appreciate the work that is being done in that particular field by your team. I already commented on Brad's post regarding .NET RIA Services, but as I'm really interested in your thoughts regarding my idea, I'm repeating this comment here as well. My company is developing several RIA applications, that combines the strengths of ASP.NET, ASP.NET AJAX and Silverlight and in the last couple of months we hat major problems in bringing our business functionality to the client without bringing our business logic to the client. We finally chose a similiar approach as you did by introducing a universal service facade that can be used by any client assembly, regardless of its position (local using a reference to the core assembly or remote using wcf). I'm currently writing an article series about this topic for a leading .NET magazine is Germany and how we solved the problem of effectively transporting entity graphs to the client using DTO's. You can find a shorter, conceptual version at http://jgnk.spaces.live.com/blog/cns!457F4BDBA1A371A5!327.entry. Tell me what you think and maybe how Microsoft is going to solve the problem with lazy loading-enabled object graphs that are transported across the wire.

Thank you very much,
Julius

Erno de Weerd

Posted on 3/21/2009 @ 3:39 AM
It feels a bit strange to me, perhaps I am overlooking something...

It seems as if you are trying to transform the ASP.NET application architecture into a RIA. The way I look at RIA's is by forgetting about the web and going back to desktop application architecture. The fact that a RIA is downloaded from a web server and (might be) running in the browser is just a matter of infrastructure. The application architecture of a RIA is, IMHO, fully comparable to a desktop application that is accessing services. The former Smart Applications come to mind. Silverlight simply allows RIA development that is more multi-platform (requires just the Silverlight plug-in), uses a .NET programming model (more or less WPF).

Perhaps I am oversimplifying or it might be my age; we're back to true client-service programming and on longer bound to that silly request/response model that was never meant to build application with.

marco ensing

Posted on 3/21/2009 @ 9:50 AM
I'm having some troubles to get to the walkthrough PDF doc. Can somebody confirm that this link is working?

Sigurthor

Posted on 3/21/2009 @ 4:54 PM
the link works

Steve Gentile

Posted on 3/21/2009 @ 5:57 PM
My biggest curiosity is how RIA will interact with ADO.NET data services.

ie. I picture in an enterprise level application that ADO.NET data services will be the service -> data layer. RIA will take the role of business layer to interact with presentation layer.

Now, as a developer, I'd like to be able to say 'hey, I started in this RAD environment with RIA but the application is growing and I need to refactor out the service/data layer and implement, ie. ADO.NET Data Services'. It would be most convenient of course if this was as seamless as possible.

And alternative would be to go ahead and define your 'RIA' as really your 'Domain.NET Services' layer that provides the glue between ADO.NET Data Services and the client.

Obviously I see much overlap here, so it's cloudy to me.

I tend to develop with the following 'tiers':

Client
Domain
Repository
Data Layer of NHibernate/EF/Linq to SQL

So we would have
Client == Silverlight/Ajax/Web - ASP.NET MVC/WebForms
Domain == DomainServices - RIA ***
Repository == ADO.NET DataServices wrapping up my data layer / data context

*** ie.this could take my EF 'Customer' object and make it suitable as a DTO - providing that glue. Much code currently goes into handling this, and what I saw in your video is perfect and takes out this effort in a more seamless way with validation, business rule checking, etc...

ie. Client - Silverlight showing a Customer
Domain - Customer 'DTO' - observable, validation, CRUD
Calls made through ADO.NET Data services which connects back to NHibernate, EF, Linq to SQL, Azure, etc...

My current 'worry' with RIA is that it might try to take over that ADO.NET data service layer - which I see as the repository/service layer and be tough to refactor out as needed

Just some thoughts on the matter :)

David Aminga Nyaoso

Posted on 3/21/2009 @ 8:59 PM
I have to create my first RIA app using the Walkthrorugh that comes with the Beta 3 documentation(PDF).

part of my conext class is as foollows:
public OrderContext() :
base(new HttpDomainClient(new Uri("DataService.axd/Tutorial1-Web-OrderService/", System.UriKind.Relative)))
{
}

AND MY MANIPAGE Cctor is :
public MainPage()
{
InitializeComponent();
OrderContext ctx = new OrderContext();
this.TheDataGrid.ItemsSource = ctx.Orders;
ctx.LoadOrders(); // Error occurs after executing this line
}

The error message is this:

The URI prefix is not recognized.

at System.Net.WebRequest.Create(Uri requestUri)
at System.Windows.Ria.Data.HttpDomainClient.BeginQueryCore(String queryName, IDictionary`2 parameters, IQueryable query, AsyncCallback callback, Object userState)
at System.Windows.Ria.Data.DomainClient.BeginQuery(String queryName, IDictionary`2 parameters, IQueryable query, AsyncCallback callback, Object userState)
at System.Windows.Ria.Data.DomainContext.<>c__DisplayClass11.<Load>b__e(Object )

I have a feeling i might have missed some configuration option on my machine running windows 2008, VS 2008 with SP1.

Can someone help.
Thanx
Nyaoso David Aminga

Nikhil Kothari

Posted on 3/21/2009 @ 9:14 PM
@Julius - will take a look at your link.

We do support defining a graph of related entities to be sent down to the client, either in a single request or across multiple requests, i.e. lazy load related entities etc. In either case, the client-side infrastructure will allow you to navigate associations (eg. Product to its associated Category). What we don't support is automatically issuing a web request when you dot into a property. For example, if you have loaded a Product instance but not explicitly loaded its associated Category, then product.Category will return null. Later if/when you do load the particular category instance into the client view, then the reference will become non-null.

Nikhil Kothari

Posted on 3/21/2009 @ 9:18 PM
@Erno
I think almost all modern/interesting RIAs have a home web server - and asp.net makes a great platform. Hence the idea to use ASP.NET as a foundation for an end-to-end RIA framework. This does not mean request/response for every operation. There are still requests and responses but they're more chunky - you load a bunch of data, work on it for some time, potentially accumulate a number of changes, and then submit all of those in one shot. .NET RIA Services is especially optimized for such unit-of-work scenarios.

Hope that clarifies things...

Nikhil Kothari

Posted on 3/21/2009 @ 9:23 PM
@Steve
.NET RIA Services focuses on the programming model between the client and the server - the domain service and domain context and emphasizes those for the developer. It implements the underlying machinery using services. We're looking at building on top of WCF/ADO.NET Data Services for that machinery. It also means you'll be able to write explicit services, those that you define for consumption by "other applications" using the same technologies in a synergistic manner.

The DomainService on the server itself can talk to any flavor of services, in addition to things like repositories and databases - the MIX demo I had on Azure was in fact using ADO.NET Data Services under the covers, since that is the API for Azure Storage. It can also talk to some other SOAP services you might have. Or it might talk to other specific RESTful services like Amazon, Twitter etc. I definitely need to do a sample demonstrating a repository.

Nikhil Kothari

Posted on 3/21/2009 @ 9:26 PM
@David - can you make sure you're not launching the Silverlight app using a test html page as using the file protocol? You need to make sure you're setting your Web app as the startup project and run from there, so you're using the http protocol to launch the app.

Frankly, I just turn off the ability to run a Silverlight app directly by mucking with the .csproj and turning off the test page creation and the ability to run directly as an app. I wish it were so by default, since most apps make sense to be run over http.

Onur Gumus

Posted on 3/22/2009 @ 6:19 AM
Yet another dead born technology from MS. Code generation is never way to go. We are programmers not IDE monkeys. I wonder when MS will really understand this.

Nikhil Kothari

Posted on 3/22/2009 @ 8:19 AM
@Onur -
Code-gen and code generators are a choice. If you're particularly interested in hand-writing the code, you can always do so - I don't see why you feel particularly blocked by the existence of a code-generator if thats what you want to program. Code-gen also produces honest to goodness regular code.

You can also choose to turn off the resource file code-gen from resx files, the service proxy for WCF services, the dynamic code-gen for asp.net files, and wherever else code-gen tries to simplify life for the mainstream programmer! If you're in the dynamic language camp, do you use any of the dynamic runtime-generated code (eg. scaffolding in ruby)?

Perry Stathopoulos

Posted on 3/22/2009 @ 2:17 PM
While many have compared .NET RIA Services to ADO.NET Data Services, I see it more as a WCF replacement/conflict. Today I use WCF to add my domain logic before connecting to my data where ever that may be.

Nikhil, .NET RIA Services certainly handles a lot of the plumbing I have to do today and that's great! I also impressed with what you call "Scalable Pattern". The question that I believe needs addressing is what use case scenarios should we use WCF and when should we use .NET RIA Services. They appear to solve the similar problems.

Perry Stathopoulos

Posted on 3/22/2009 @ 2:46 PM
Also what about SOA pattern, has been proven too heavy for real world scenarios and .NET RIA Services is more of an evolution in practicality?

I'm anxious to hear your thoughts.

Joe Mayo

Posted on 3/22/2009 @ 3:28 PM
Hi Nikhil,

Good stuff! I see lots of possibilities here and really like how you guys have gone after pain points like validation in multiple tiers, simplifying asynchronous patterns, making it easier to work with entities accross tiers. Where will the discussion forums be?

Joe

Nikhil Kothari

Posted on 3/22/2009 @ 11:31 PM
@Perry
The way I see it:
.NET RIA Services:
- Pattern for writing app logic and consuming/managing data on the client
- Infrastructure to expose app logic in the server to its client projection (whether its SL/WPF/Ajax/Server-rendered HTML)

WCF:
- Framework for writing services that implement a specific contract designed for exposing app logic and data to other applications that evolve independently. Other apps could be other apps within the same organization or cross-organization. I point that out as I am not using org as the differentiator.

I definitely agree with you - I see .NET RIA Services very well aligned with WCF. Even have a prototype of it, which yields some interesting tangible customer value. More on this in the future.

I think SOA is a very high level general philosophy and I think at that level, everything makes sense. There are some fundamental tenets that make it applicable for cross-app communication. There are some aspects about purist SOA-based implementation that don't deliver enough value for the effort required (eg. don't share implementation) when you're talking of within-the-app communication, the .NET RIA Services scenario. .NET RIA Services builds on a services story for its implementation. It however emphasizes the programming model between the two tiers in a more practical way rather than focusing on (and requiring the dev to focus on) the lower level communications infrastructure.

@Joe
Discussion forums are on http://www.silverlight.net.

Onur Gumus

Posted on 3/23/2009 @ 1:52 AM
@Nikhil

The code generation shows the weakness of the language. That's why dynamic languages doesn't require code generation because they are not bounded by the compiler checks. Though personally I still think static languages are better. Bigger projects are becomes harder to debug and maintain with dynamic languages. The examples you gave, are different. The code generation notion I mention doesn't mean that everything that generates code is bad. Even a C compiler generates machine code, asp.net generates HTML and the list goes on. The rule of thumb is "if you have to mess with the generated code, meaning if you can't black box it you are in serious trouble. Examples ? Typed datasets which were catastrophic , I also think Linq to SQL is catastrophic . Also asp.net web sites (not web applications) are catastrophic. I don't use any of them and I observed many times the users of those technologies are doomed. WCF proxies asp.net code behind stuff is different, because you can 100% black box them. So they usually don't cause much problems. Unfortunately MS ignored macro based language features like Boo and Nemerle has and they still lean towards code generation. You will see, this is another dead born technology just like typed data sets.

Nikhil Kothari

Posted on 3/23/2009 @ 7:18 AM
@Onus -
Interesting ... the predictions are already starting ... there must be some interest thats causing someone to bother! :-)

What I find even more interesting is it is based on beliefs of absolute truth in black and white manner based on words such as "never" as in "Code generation is never way to go". Yes, I am aware that there is a whole group who believes in that. Thankfully MS frameworks and tools have such a broad spectrum of customers, that it keeps folks working in check so it is near impossible to say things like "never", "always", "every", "all".

You say that when you can black box the code, it is ok. However the examples you say are ok - service proxies, asp.net code gen etc. are also not black box, or are just as black box as the .NET RIA Services code generation in my personal experience.

Personally, I wouldn't say that .NET RIA Services applies to _every_ developer and _every_ app. It has a certain sweet spot it is geared toward (shouldn't every technology?), and caters to a range of scenarios around that.

Peter O'Toole

Posted on 3/23/2009 @ 8:04 AM
Nikhil,

Is it safe to assume that the new Binary XML format will be baked in as an option? Of course I want my services for 3rd party apps to be atom or something similar, but when talking between silverlight and the server I feel the need for speed!

--Pete

Nikhil Kothari

Posted on 3/23/2009 @ 9:07 AM
@Peter - we're working on binary encoded messages. While I don't put it in the must-have critical bucket, its super nice. Agree with the need for speed... and lower bandwidth consumption as well. I do have a prototype... its not in the bits, but I am hoping it can become more real a little bit further down the road.

alexandre Roba

Posted on 3/23/2009 @ 12:06 PM
Hey Nikhil,
I tried to use the RIA .NET Services and I was convince by the archtiecture but I found something missing.

Most of the time my query methods perform a paging on the server side. In order to display the proper information I need for every query, two returned values. The list of the entities for the current page, but also the total number of items in the list. According to the convention used for the RIA service, I should use the [custom] methods... But It is a query.... I beleive the server side paged query should be taken into account and included properly in the possible querry methods.

Keep doing the good work.

Alex

Nikhil Kothari

Posted on 3/24/2009 @ 6:33 AM
@Alexandre
For returning total count information we take your query from a query method, compose any incoming query and then perform the equivalent of IQueryable.Count() operation by virtue of calling the Count<T> method on DomainService. You can override Count<T> to customize the counting.

So you don't need to use a custom method just for returning total count in addition to the data itself.

Note that you may not want to return total count always, if computing it is expensive. The client controls work in enhanced mode if total count is available, and degrade to something like next/prev paging if total count isn't available.

Flavien Charlon

Posted on 3/24/2009 @ 11:21 AM
Exposing IQueryable seems pretty dangerous to me. It means that anybody can run all sorts of queries against the store. If we have a table with 10 millions of records, and expose it through IQueryable (let's say I use paging from my Silverlight application), anybody can use the service directly (bypassing the SL app) to return all the 10 millions records, it will most likely put SQL Server on its knees, and use a lot of bandwidth. Some operations might also be inefficient against the store (WHERE on a non indexed column).
I think we should have an easy way to restrict what operations can be used against IQueryable.

Nikhil Kothari

Posted on 3/24/2009 @ 11:35 AM
@Flavien
What is being exposed is the IQueryable that your query method exposes, and _not_ an IQueryable over the underlying table. So you have the option of filtering down to only the relevant rows. Your query method can also take requried parameters which further help you filter/shape the data you hand out as represented by that IQueryable, and also help make sure you have some indexed columns in your query against the data store.

Second you do have the option of turning off client-side queries by marking a query method as [Query(IsComposable = false)] and exposing only parameters.

Regardless of what your method does, the incoming query from the client is composed on top of that IQueryable returned from your method, so the most it can do is filter further... and not expand the set of results you can get at from the client.

Finally, and this isn't in the current bits yet, but we're thinking of various throttling type of controls - for example you might be able to annotate a query method as bounded to return at most n entities... that sort of thing.

Phil Cockfield

Posted on 3/24/2009 @ 5:40 PM
Hi again Nikhil,

Thanks for the response about auth providers - that makes sense. I have a question about object graphs - I'm sure I'm doing something stupid, as there was some discussion above about object graphs (and that they were supported, and were just lazy loaded).

I'm deriving directly from [DomainService] and constructing my own DTO objects myself, rather than have them served up from the a LINQ provider via the [LinqToEntitiesDomainService]. This is because I have a strange data-source that doesn't fit nicely within a single relational DB, and it's easier to just pull the data together and build DTO's.

Anyhow - the issue is, if I have [ClassA] and [ClassB]
With this relationship:

public class ClassA
{
[Key]
public string Text { get; set; }
public ClassB MyClassB { get; set; }
}

The 'MyClassB' property is not being included in the generated code on the client. It's just omitted - yet the other properties are there fine. Is there some additional attribute I need to include here, or something else I should know about?

Thanks Nikhil! This stuff is quite awesome.

Nikhil Kothari

Posted on 3/24/2009 @ 6:21 PM
@Phil
You have to mark the MyClassB property with an [Include]. This tells our serializer that you're interested in sending the referenced member (as opposed to using it only server-side).

Koistya `Navin

Posted on 3/25/2009 @ 9:17 AM
Interesting technology.. I am keen to see WPF, ASP.NET MVC and AJAX client suport in it.

The only concern I have so far is security.. will it be able to restrict unauthorized quering and update operatoins based on user roles? That would be great to set these access rules on per entity as well as per property basis using metadata.

For example (per property):

[Authorize({"Administrators", Permissions = Permissoins.ReadWrite }, {"*", Permissions = Permissions.ReadOnly })]
public string Name { ... }

Phil Cockfield

Posted on 3/25/2009 @ 11:55 AM
>> For example, if you have loaded a Product instance but not explicitly loaded its associated Category, then product.Category will return null. Later if/when you do load the particular category instance into the client view, then the reference will become non-null.

Is there a way (via an Attribute??) to force load objects associated by property? I'm doing the above ClassA=>ClassB thing we discussed previously, but I find when I bind the result set to the grid, the ClassB's don't show up immediately. However, if I scroll a row offscreen, and then back on I find that the data appears - meaning it must have forced a redraw, and subsequently the binding, and the ClassB data had been loaded in the mean time.

What's the load-lifecycle that' happening here under the hood?
---
If I can't (shouldn't) force the loading of the entire object graph, can you perhaps point me in the direction of the specific events (Loaded??), and methods I should be calling to get this data up on screen after the initial async callback?

Thanks - sorry if my language is a little vague. I hope the question makes sense - I'm not quite sure what precisely I should be asking for. Thanks Nikhil!

Nikhil Kothari

Posted on 3/25/2009 @ 2:41 PM
@Koistya -
The framework does support authn/authz type of rules you can attach to the methods on your DomainService. See [RequiresAuthentication] and [RequiresRoles]. You can also put these attributes on the domain service and they inherit down.
Today, we don't have support for putting those on a per-field basis.

@Phil
The [Include] attribute tells the serializer whether to send down a referenced associated object. The code in your query methods on the server determine whether to load the associated object into the middle tier from the backend-store.

You shouldn't be seeing the behavior where scrolling something offscreen and then back on causes the associated object to appear. From your description, it sounds like there is a bug in here, where the change notification on the associated object property isn't being raised at the right time. Can you try to package up a small repro and post as a bug on the forums?

Basically when you call load, we issue a request to the server, get the results (which contain the top-level entities you queried for, and related/included entities), and we merge them into the entity lists on the client. We should be raising change notifications as needed along the way...

Phil Cockfield

Posted on 3/25/2009 @ 7:22 PM
Yep - I'll recreate and post. Might spot the problem when paring everything down...but if not I'll push it over to the forum. Thanks.

Alexander G. Bykin

Posted on 3/27/2009 @ 8:15 AM
perfect pattern.
easy to learn, easy to use.
thank you Nikhil and MS.

we are wait for release :)

Russian Dev.

Sean Capes

Posted on 3/30/2009 @ 7:03 AM
Hi Nikhil,
Good stuff, I've been looking for patterns for implementing SL apps and this is great start, I'm not keen on writing the plumbing for persistence. The one issue with this, as always, is when the auto generation fails. I'm currently having issues getting the many to many relationships generated in the client context. The relationship exists in the .designer.cs and entity model but isn't generated for the client. Is there any way to debug what is happening in the code generation? How do I find out all the attributes and info on how the code gen works?
Thanks in advance, great work.

Nikhil Kothari

Posted on 3/30/2009 @ 9:02 AM
@Sean
You'll want to make sure you set up your data model to have the intermediate table in your many to many relationship, so it surfaces as two one-to-many relationships.
In general, we do report a bunch of errors when code-gen fails to guide you. It seems we aren't detecting and raising errors for many-to-many. Can you file a bug on the forums regarding better error reporting for this specific case.

Eoin

Posted on 3/31/2009 @ 1:08 PM
Hi,

How do we do debugging in .Net RIA Services.
I've developed a Silverlight application, but I can't seem to step into the server side of the application.

If you have any information or some links I can check out.

You can e-mail me if you prefer.

Thanks,

Eoin

Nikhil Kothari

Posted on 4/1/2009 @ 7:50 AM
@Eoin - make sure your web project has debugging for both Silverlight and managed code turned on. If you F5 and have breakpoints on client and server code that should work, and you should even able to step from one bit of code to the next seamlessly... no special steps should be required.

Onur Gumus

Posted on 4/5/2009 @ 12:53 PM

Eoin

Posted on 4/8/2009 @ 2:03 AM
Hi Nikhil,

Thanks for the earlier help - got it working :)

But I'm having a new problem with the .Net RIA services and nobody seems to be able to figure it out.

Can you have a look at the error here
http://silverlight.net/forums/p/87026/203126.aspx#203126

Thanks, hope you can help

Eoin

Mihir

Posted on 4/11/2009 @ 10:19 AM
Hi,
I am working on building a Silverlight 3 Application using .RIA Services for a LOB application.
I am currently developing classes called DAOs which give functions that connect to the generated code in the Silverlight project.
I call these functions in the Child pages.
My problem is the database takes certain time to load up and hence the page doesn't show the proper results.
I was trying something out using the "Loaded" event handler & "IsLoading" Property to update the xaml page when it loads.
What would you suggest to solve this problem on all pages?

Thanks, hope u can help
Mihir

Nikhil Kothari

Posted on 4/11/2009 @ 3:36 PM
@Mihir - there are lots of solutions for dealing with async, and keeping the user informed of the underlying work that is going on. It really depends on your particular application and the particular scenario, so its hard to suggest any one definitive approach. The solution may range from not showing activity, to showing it in some passive manner, to blocking further user action until the activity is done.

Generally speaking however, the IsLoading and Loaded events are low-level building blocks for knowing whats going on... and what you layer your particular solution on.

Deepak Chawla

Posted on 4/15/2009 @ 12:04 PM
How can we integrate this methodology with MVC???

Volodymyr Kovalenko

Posted on 4/16/2009 @ 4:59 AM
Hi,
Really cool framework )
But what about some renaming strategy or pattern. I understand that you trying to erase border between server and client code. Though generated classes have different code or can be extended by partial classes with different code. And it's confusing when they all are members of one namespace. Besides it's very strange to use SomeClass from WebServerNamespace on Client.

Nikhil Kothari

Posted on 4/16/2009 @ 8:00 AM
@Deepak - We have a prototype and thoughts on how you'd use domain services from an MVC controller. We hope to share more details in a future preview release.

@Volodymyr - In my samples, I try to stay away from a "WebServer" namespace. The namespaces I typically use are App, App.DataModel and App.DomainLogic. There is nothing server or client about them. They are about the app first and foremost.

Steve Gentile

Posted on 4/18/2009 @ 10:57 AM
Been awhile since the mix talk. Time to evaluate this further.

I would prefer if this solution had only a 'DomainService stub' in the asp.net web application. The DomainService would exist in another layer/assembly

Silverlight UX -> Web Application -> DomainService -> DAL,etc...

See, I don't think of my 'domain' and business logic as existing within my web application project.

I've never been on a project of any significance that put domain logic classes inside the web application. ie. my MVC app doesn't put business logic in controllers.

View -> Controller -> Services Layer -> DAL Layer

I'm not seeing this yet in RIA.NET ?

Just thinking here, but a DomainService project that you referenced from your asp.net web app that contained the domain logic/DAL access would be a better move IMO.

Nikhil Kothari

Posted on 4/18/2009 @ 1:23 PM
@Steve -
We will have a story for putting domain services in a classlibrary and then having a corresponding Silverlight classlibrary as part of a pair, and then allowing you to reference those in a web app and a corresponding Silverlight app.

We will continue to offer the ability to put domain services in a web app, as sometimes it is just fine to use organization of code into namespaces/folders rather than physical assemblies... esp. as a way to get started, rather than forcing you down a particular path.

Vimal Nair

Posted on 4/27/2009 @ 4:12 PM
Hi Nikhil,

We are currently planning on porting a desktop application to Silverlight based Web application and we expect the port to take 5-6 months to complete. At this point, using SL3 and RIA services will definitely be helpful in reducing port time and also future maintenance. However, SL3 is still in BETA. I understand that you cannot provide an official release date. Without providing any official confirmation, would you recommend using SL3? The concern we have is that technology presented with the BETA bits could change drastically forcing us to spend a sizeable chunk of time to port to the release version of SL3. Your opinion will definitely be helpful.

-Thanks

Julien

Posted on 5/2/2009 @ 2:17 AM
I follow to what Steve Gentile mentioned.
Is it possible to use DomainServices from ServiceLayer to DataAccessLayer soon?

Nikhil Kothari

Posted on 5/2/2009 @ 7:19 AM
@Julien - not yet, but it is on our roadmap for v1.

Axel

Posted on 5/7/2009 @ 7:44 AM
Hi Nikhil,

Thanks for this wonderful SDK! It really saves a lot of work und I love it because it also supports plain CLR (POCO) objects, so one can use it with any data access layer framework (subsonic in my case).

However I have a problem filling recursive structures for displaying in a silverlight TreeView control.

I tried to design the object like this:

public class MyItem
{
public MyItem()
{
SubItems = new List<MyItem>();
}

[Key]
public Guid ID { get; set; }

public string Text { get; set; }
public MyItemType ItemType { get; set; }

[Association("SubItems", "ID", "ID")]
public List<MyItem> SubItems
{
get;
set;
}
}

The DomainContext and the client proxy objects have been generated as expected. When I fill call my Load method in the DomainContext class the service is also called as expected. Debugger shows that on server side all objects and subitems are filled correctly.

However on the client side, the subitems are filled with an endless recursive structure like this root.SubItems[0] == root

I guess the association

[Association("SubItems", "ID", "ID")]

is responsible for that?

But how can I set the association correctly? I did not find any documentation on this, yet.

Thanks in advance

Axel

Thameem

Posted on 5/7/2009 @ 2:32 PM
Hi Nikhil.,

Thanks for the Great Stuff!!

I am trying to implement a Silverlight control, where the interaction to the DomainServer would be from inside the Silverlight control, say it could be like this.

<XAML Markup >
<SilverlightControl x:Name="silverlightControl1" ../>
</..>

in CS

silverlightControl1.Context =??

how do I assign the context the control so that this could access the DomainServer..??

Thanks,
Thameem

Nikhil Kothari

Posted on 5/9/2009 @ 5:27 AM
@Axel
Generally for those sort of relationships, you have a ParentID member on your type and the association is not ID <-> ID, but from ParentID <-> ID.

@Themeem
Why doesn't this work?
silverlightControl1.Context = new MyContext();

Vishnu

Posted on 5/20/2009 @ 10:32 AM
Many-to-many relationship works fine with intermediate table until you want to remove an entity reference from the first or the last table to the intermediate table.
If we remove it throws and error saying entity key cannot be modified. To reproduce this, create a table called users give it userid as key, then create another table called roles give it roleid as key.
Now create an intermediate table called UsersInRoles and make key as userid, roleid and try to delete the roles assigned through user entity.

Vishnu

Posted on 5/21/2009 @ 4:24 AM
OK I figured out this one, you cannot use entity collection remove to remove the intermediate table entry, you have to use the intermediate table to remove entries from the same, also found that this is handled correctly in .net 4.0, only time will tell

Kyle Burns

Posted on 5/29/2009 @ 4:10 AM
You mention in response to Steve Gentile's question that a story exists for providing further seperation between presentation services and domain logic. Can you elaborate on this? I am particularly interested in a reference application demonstrating how we can gain the rich binding and validation support offered by RIA services while meeting strict requirements preventing direct access to database servers from the DMZ.

Mladen

Posted on 6/17/2009 @ 7:43 AM
Hello, we have started new project which will use SL+RIA services and we ran in some problems.
We have list of users on server side shown as a grid on client.
Scenario is: I call operation CreateNewUser on ViewModel, this calls CreateUser on server which will create new User and add it to list of users.
After this I'm calling LoadUsers on VieModel._userContext to load new list and to show it in UI.
Problem is that Load method on server is called first (actually method is called GetUsers).
Problem is as I can see in synchronization but what is solution?

Ysh

Posted on 8/3/2009 @ 2:47 PM
How to access the DataService through https? I have a SL3 application on my local machine that talks to a secured riaService (https://webserver03:488/dataService.axd/MyRia-Domains-Authentication-AuthenticationService/) in another web server which has self-signed certificate. When I run the application, I get the "Security Error" in EndLoadUser() function of AuthenticationBase. I do have a clientaccesspolicy.xml in the webserver. However, I have not problem running the application if the riaService points to a http site on the same web server (http://webserver03:488/DataService.axd/MyRia-Domains-Authentication-AuthenticationService/). What could be the problem?
Ysh

Mike

Posted on 11/3/2009 @ 5:02 AM
I've just realized that some RIA services exist....are they designed solely for Silverlight or other technologies welcome as well? (Flex?)
Cheers,
-M

mohammad

Posted on 11/5/2009 @ 3:36 AM
s
Post your comment and continue the discussion.