none
[ServiceOperation] --> [Invoke] not working

    Question

  • Hi,

    After the upgrade to WCF RIA Services the following no longer works:

                [Invoke]
                [RequiresAuthentication]
                public UserAuthorization GetPermissionsOrder(tblOrder Order, int AccountID)
                {
                    return new UserAuthorization(); // TODO
                }

     As per the breaking changes I changed [ServiceOperation] to [Invoke] but am still getting the error:

    Operation named does not conform to the required signature. Return types must be one of the predefined serializable types

    Thanks

     

     

    Tuesday, November 24, 2009 3:09 AM

Answers

  • The new version does not allow [Invoke] operation to return entity types anymore.

    Tuesday, November 24, 2009 3:44 AM
  •  OK, so how to resolve it to work? - Operation to return single entity type.

    That is what a Query method is for.

    Tuesday, November 24, 2009 10:06 AM

All replies

  • The new version does not allow [Invoke] operation to return entity types anymore.

    Tuesday, November 24, 2009 3:44 AM
  •  OK, so how to resolve it to work? - Operation to return single entity type.

    Tuesday, November 24, 2009 5:00 AM
  •  OK, so how to resolve it to work? - Operation to return single entity type.

    That is what a Query method is for.

    Tuesday, November 24, 2009 10:06 AM
  • So you have to stick a single value in an IEnumerable and do a FirstOrDefault on the Client side? Or can a Query return a single value?

    Tuesday, November 24, 2009 12:36 PM
  •  Here is a simple Query method which will return a single entity:

    public Customer GetCustomerByID(string ID)

    Get is as you know a prefix to mark the method as a Query method, you can also add the [Query] attribute if you don't want to use the Get prefix.

    Tuesday, November 24, 2009 12:41 PM
  • The latest 2010/.NET 4.0 bits DO allow service operations to return entities and collections of entities. We made that change to the 2010 bits but not the 2008 bits. Which are you using? However, I do agree that a query method might be better suited to your purposes.

    Tuesday, November 24, 2009 12:46 PM
  • So in other words,

    You can simply do the following:

    public class MyDomainService : ..........

            //Optional [Query]
            public Customer GetCustomerById(string id) { .... }

     

     On you Client Side:

     _context.Load(_context.GetCustomerByIdQuery(), LoadBehavior.KeepCurrent,
                                 dataLoad => {
                                      ...
                                      var customer = dataLoad.Entities.FirstOrDefault();
                                      ...
                                  }, null);

     

    Tuesday, November 24, 2009 12:47 PM
  • Correct.

    Tuesday, November 24, 2009 1:04 PM
  • Thanks all, I'm still working this problem and many others so when I get this this I'll update the thread with my final solution.

    Wednesday, November 25, 2009 1:04 AM
  • The latest 2010/.NET 4.0 bits DO allow service operations to return entities and collections of entities. We made that change to the 2010 bits but not the 2008 bits. Which are you using? However, I do agree that a query method might be better suited to your purposes.

     

    So there is no way for WCF Ria services for VS 2008 bits to operation to return single entity? And this work only for 2010 bits? So this is now a bug in 2008 bits and everybody who want to return single entity have to return IEnumerable<Entity>?

    Wednesday, November 25, 2009 9:22 AM
  •  Yes, sort of.. But remember WCF RIA Services is in a Beta stage not an RTM version.

    Wednesday, November 25, 2009 9:47 AM
  • So there is no way for WCF Ria services for VS 2008 bits to operation to return single entity? And this work only for 2010 bits? So this is now a bug in 2008 bits and everybody who want to return single entity have to return IEnumeable<Entity>?

    No, a Query method can return back a single entity and has been able to do that since the July preview. If there is an issue here it is that there isn't a seperate LoadOperation for a single entity query so you have to use the regular LoadOperation which doesn't have a property for returning a single entity.

    The VS2010 Invoke operation can return an entity type but you still shouldn't be using the Invoke to load an entity. The Invoke in VS2010 can now return an entity type to make it easier to get complex returns types from an Invoke but using it to load a single entity is still a misuse of the Invoke.

    I don't think anyone has ever asked why anyone cares. Why does it matter to you that you have to do a LoadOperation.Entities.SingleOrDefault to get your single entity back from the LoadOperation instead of something like LoadOperation.Entity? Every time this comes up someone seems to think this is a problem but never says why it is a problem.

     

    Wednesday, November 25, 2009 10:07 AM
  • Ok, you are right. Now I see it works. I was confused, that for my opeation

    public Something GetSoething() {...}

    I had previously labeled by [ServiceOperation] so I changed it to  [Invoke] and it didn't work. So I changed it to [Query] label and it didnt work too - compile error. Then I removed attribut and it compiled well. But on the client the operation was not available, so I was confused. And the reason is the operation has now suffix "Query". Of course !

    I don't think anyone has ever asked why anyone cares. Why does it matter to you that you have to do a LoadOperation.Entities.SingleOrDefault to get your single entity back from the LoadOperation instead of something like LoadOperation.Entity? Every time this comes up someone seems to think this is a problem but never says why it is a problem.
     

    Ok, now it realy doesn't matter.

    Thanks

    Wednesday, November 25, 2009 3:12 PM
  • Ok, now it realy doesn't mater.

    Good, still wondering why the people who complained about it in the past cared. Worried that there is some use case that is really being missed.

    Wednesday, November 25, 2009 3:14 PM
  • The latest 2010/.NET 4.0 bits DO allow service operations to return entities and collections of entities. We made that change to the 2010 bits but not the 2008 bits. Which are you using? However, I do agree that a query method might be better suited to your purposes.

    This is a step in the right direction. Here http://forums.silverlight.net/forums/p/118165/327139.aspx#327139 I thought it wasn't supported. Very confusing, please update the documentation for clarity. Still I tried a simple example with Customer that has an Addresses association, but when passing a Customer entity to the invoke operation, the Addresses-collection is null on the server end. This is not what I expect. I expect to be able to either mark the associations that need to travel the other way or mark the associations that should be excluded. There are typical scenario's which involves a server roundtrip of a partial object graph to update the graph. For instance if you change a particular entity field, it might require a server operation to massage the entity. You would like the changed object graph to be merged in the client entity set. With this in place WCF RIA is really useful....

    Thursday, November 26, 2009 2:19 PM
  • I don't think anyone has ever asked why anyone cares. Why does it matter to you that you have to do a LoadOperation.Entities.SingleOrDefault to get your single entity back from the LoadOperation instead of something like LoadOperation.Entity? Every time this comes up someone seems to think this is a problem but never says why it is a problem.

    i woudn't call it a problem... but LoadOperation.Entities.SingleOrDefault doesn't look as good as LoadOperation.Entity... specially when analysing someone else's code one may have to wonder "why is this code ignoring the rest of the collection?"... it's just like using query methods to return entities instead of invoke methods.. both of them can return entity collection (well in this new release they can't anymore for VS2008) BUT query methods make more sense (they were made for this purpose just like entity collections are supposed to return a collection of entities...)

     as i see it, its just a matter of concept...

    but anyway, this is becoming a little "off subject"..

    about the allowed return types in InvokeOperations, i'm glad to know that it works with .NET4 bits and VS2010, because i'll have to create a "query method" that will invoke actions on server, just so i can use my composed return type.

    again.. it works.. but it looks ugly

    :D

    Monday, November 30, 2009 9:01 AM
  • as discussed, since we can't return composite types with Invoke methods using WCF RIA Services (VS2008/.NET3.5), query methods would have to be used instead.... returning that composite type.. i didn't like this solution to begin with because, in my case, it would be used to return compilation errors of a method that will compile code and  generate a dll to be used by another software... so as you can see there is nothing to be queried there

    anyway it seemed like it would work, so it wasn't a big deal because it's a beta version and all....

    but i just couldn't make it work... several kind of errors, lots of restrictions, and it kept looking worst

    so i decided not to spend a lot of time on this (again: its a beta version!): i serialized the composite type into xml and passed it to the client with an invoke method returning a string.. i already had a class to handle this kind of serialization, so it was really easy

    and it works perfectly!

    it's a different approach, so if you're having problems returning composite types, try this!

    Monday, November 30, 2009 11:47 AM
  • I don't think anyone has ever asked why anyone cares. Why does it matter to you that you have to do a LoadOperation.Entities.SingleOrDefault to get your single entity back from the LoadOperation instead of something like LoadOperation.Entity? Every time this comes up someone seems to think this is a problem but never says why it is a problem.

    I am fighting my way through figuring out how to best use RIA Services and this question jumped out at me.  The reason we care is that not every business application fits into the "Customer wants to place an order" use case that seems to be what Microsoft designs their frameworks around. 

    For instance, I have a Silverlight form that needs a set of user options that are in a complex data type that encapsulates a dozen or so textual entries.  I *could* put it in an XML string and return it as one person suggested but what I *want* to do is return an entity object called "Filter" and let the framework do the serialization magic for me.  Instead I am going to rewrite things to load up a list of exactly one every time and then get the FirstOrDefault as suggested instead of Value. I could of course ask for a series of strings that represent each option or I could...  well the list goes on and on!

    There are lots of workaround but they are all just that... workarounds.  I am open to the possibility that my thinking about architecture is too limited or perhaps that I am simply using RIA Services wrong, however I also think that Microsoft writes too often for the demo app and not often enough for the real world. Just one guy's opinion though! :)

    Bottom line is this, for those of us who used a ServiceOperation to return an entity type before, we now have to go back and change those all to Query operations.  It's not just a matter of changing from "LoadOperation.Entity" to "LoadOperation.SingleOrDefault" it's changing from an InvokeOperation.Value to a LoadOperation.FirstOrDefault along with calling Load instead of calling the service method directly.  It's not a lot of work... but it's work and that's why I care!  :)

     

    Monday, November 30, 2009 7:37 PM
  • Can you give me more detail on what you are trying to do MSwaffer or a link to where you had been discussing this previously? I can understand your issue about having to change things, but that is why I have been telling people not to use the ServiceOperation to load data since the beginning of the year.

    Monday, November 30, 2009 8:51 PM
  • Sure thing.  We have a reporting application in SL3 that consists of a dashboard with customizable charts along with the ability to set up and run paper based reports.  Each report and / or dashboard module can display filtered results based on user preference.  The filters consist of the usual hierarchy groupings like region, district, area along with more specific filters like manager code and employee code.  There are additional, more domain specific filters as well.

     On the server side these filters are encoded into strings that are stored in the DB. One ServiceOperation / Invoke method we were using was GetDefaultUserFilter() which does exactly what it says.  Every user has a default filter which is the most expansive filter they are allowed to run and all reports start with that filter, however the user can change it and store a copy of that filter along with that particular report.  There will only ever be one default filter and any other time I need to retrieve a filter I know exactly which one I want and can ask for it by ID so we also have GetFilter(int id).  I only ever need to get one filter back at a time for this particular app.

    I am OK with the cost (and pain!) of being on the 'bleeding edge'... it's just the way life works.  What made me raise my eyebrows in this thread was the assumption that returning a single entity would be a rare thing.  There are probably another half dozen examples just like this one in our one app and it's still in Beta. :)

     Like I said, maybe we need to rethink how we are writing our SL apps but the assumption in code samples seems to always be that we as developers are always binding data grids to lists of entities and editing them in place.  I have only been doing .NET for 5 or 6 years so maybe I am not the best judge but in the half dozen or so apps that I have worked on, we have only bound to a data grid twice and we replaced one of those with a better UI not long after. 

     Thanks for the info in the thread... it was helpful in resolving the issue today!

    Monday, November 30, 2009 10:31 PM
  • The assumption isn't that loading a single entity is rare, the assumption is that loading a single entity is a subset of loading multiple entities and LINQ already has the SingleOrDefault method to say we are expecting only a single result back from an operation so the need to load a single entity is already covered by the API. As for your particular issue, why aren't you leaving you transferring the strings as they are encoded in the database to the client and doing the processing there instead of unpacking them on the server?

    I have put together the following extension method for the LoadOperation which will give the LoadOperation an Entity property. If you think this is useful I will add it to RIAServicesContrib.

    using System;
    using System.Net;
    using System.Windows.Ria;
    using System.Linq;

    namespace RiaServicesContrib.Extensions
    {
        public static class LoadOperationExtensions
        {
            public static T Entity<T>(this LoadOperation<T> lo) where T : Entity
            {
                return lo.Entities.FirstOrDefault();
            }

            public static object Entity(this LoadOperation lo)
            {
                return lo.Entities.FirstOrDefault();
            }
        }
    }

    Monday, November 30, 2009 11:04 PM
  • The way it is now is just fine with me. Whether it's a method that returns one entity or one that returns many, either way you need to provide logic that checks if one entity was returned, just the code looks a little different. Not a big deal. The fact that all this plumbing is already written is saving me so much time it's hard to complain about anything. Transactions, concurrency, security - its' all there and I haven't written a single line of code. This means more time spent on the important things that are custom to my application rather than reinventing the wheel. Some people like to do that but not me.

    I suppose the only axe I have to grind is with the ADO.Net Entity Data Models in terms of using stored procedures for selects whose results do not fit an existing table in the database and UDF's. Devil

    Monday, November 30, 2009 11:05 PM
  • I'm not 100% sure if i'm using RIA Services the way it is supposed to be used, exactly because all the examples i see on the web are about authenticating users, placing orders and binding data to a grid or something..

    I do bind data a lot.. And RIA Services is really great on doing that!

    But i also really liked the possibility to invoke ServiceOperations... We're writing a large and complex app suite that uses several technologies, and the SL3 app is our web management tool. Part of this "WebAdmin" tool allow the user to create a script (compiled dll written in c#) that will be used by other apps. The editing of this code uses all the great things provided by RIA Services (query methods, easy data binding, etc). After editing the code, though, it needs to be compiled. So i created a ServiceOperation that does exactly that and returns the compilation messages and generated code, in one classe called "CompilerResult".

    As you can see, the most important thing about this method is the operation that generates code, compiles it and builds the assembly, not the CompilerResult entity that it returns. I don't think i'm a programming genious and i can be really wrong about it, but in my understanding "entities" are the goal of Query methods and "operations" are the goal of ServiceOperation methods (now called Invoke methods). So i just couldn't help feeling that turning this ServiceOperation methods into Query methods is wrong.

    I also have ServiceOperation methods (now Invoke methods) that sends custom commands to WindowsServices running on the server, but these only returns "bool" types, so there's no problem with them.

    Well those were just examples of an "out of the ordinary" use of RIA Services..

    By the way: i used the "manual serialization" with my CompilerResult because i don't want to change my methods to Query methods and then change them back to Invoke methods when RTM version of RIA is released. But then i started wondering if this will be a "sure feature" in RTM version. I read that it works with .NET4 bits and VS2010, but will it be still there in RTM?

    Thanks!

    Tuesday, December 01, 2009 6:10 AM
  • During the last month there aren't so many design changes more than the communication, but that doesn't mean that changes will take place during the beta stage. If you design your application correctly, and if RIA Services team removes the Service operation method (I don't even think they will do it), you can still replace the Service operation call with a simple WCF Service.. I never build an app based on a beta, if I do, I make use of wrappers, facade and proxies etc. So I can easy replace the infrastructure if needed.. But using building with a beta version, will or can result in a higher cost and time it will take to build the app, because changes can happen, and then we need to change our code to fit the new changes...

    Tuesday, December 01, 2009 6:23 AM
  • Your examples are fine, and I think you have a good understanding of how to use the Invoke correctly and I don't think you need to worry about losing that ability in the RTM. WCF RIA Services is supposed to be feature complete.

    My concern isn't you, I think what you are doing is fine, my concern is for people trying to load entities with an Invoke, then trying to bind that entity, edit that entity, and then expecting to be able to SubmitChanges for that entity. Those are the people who get hopelessly confused and get defensive when it is explained to them that they need to use a query to load the entity instead of the invoke. In my mind, the invoke is simply a way to embed a standard WCF method inside a DomainService so that we don't need to create a seperate, standard WCF service for the situations where we need to do that.The problem is how to get people to understand that distinction.

    Tuesday, December 01, 2009 8:47 AM
  • Thanks Colin!

    I'm glad to know i got it right!  I'll keep using the serialized object until RTM comes.

    But i admit that i was confused.... Now i got your point: retrieving data to bind, submit or reject changes should definitely use query methods.. because that's what they were made for and "loaded entities" have all that special treatment on the client side that makes them easy to use.

    About the distinction.. here's how i see: query methods return entities that are trackable, editable, submitable. There's a lot of special handling going on there. Invoke methods return sort of "read-only" values. They give you what you asked for and that's it: no "coming back to the server" on its own.

    Tuesday, December 01, 2009 9:40 AM
  • As for your particular issue, why aren't you leaving you transferring the strings as they are encoded in the database to the client and doing the processing there instead of unpacking them on the server?

    Mainly because this breaks our concept of object oriented programming.  We feel that rather than pass around a dozen magic strings they should instead be encapsulated inside an object that is then passed around.   

    my concern is for people trying to load entities with an Invoke, then trying to bind that entity, edit that entity, and then expecting to be able to SubmitChanges for that entity.

    This makes sense to me.  I see how we were using the framework wrong but I also see where we got the wrong idea.  Every example we saw of using the LoadOperation was a case of using a list and binding it to a grid or DataForm.  Knowing that this same pattern can (and should!) be used for single entity handling is definitely an "aha" moment. 

    A side note is that we aren't using ADO.NET Entity Framework. The reasons are way outside the scope of this thread but suffice it to say that "not having to write a single line of code" isn't a compelling argument for an enterprise application with a long support horizon.  The ability to change existing functionality quickly and confidently is more important than being able to create the functionality quickly in the first place.  Every time we have played with Entity Framework it's been great... until we had to start changing existing code. 

    Tuesday, December 01, 2009 11:46 AM
  • Mainly because this breaks our concept of object oriented programming.  We feel that rather than pass around a dozen magic strings they should instead be encapsulated inside an object that is then passed around.   

    Got it, I see what you are doing now. I am originally a database guy myself so the idea of even storing magic strings in the database is anathema to me. I can understand wanting to get it turned back into a real object ASAP. I think I saw somewhere that the VS2010 version of RIA Services either has or will be getting support for collections, that might be what you are looking for.

    As for Entity Framework, I am using it purely as a DAL between the DomainService. I think EF 4 is going to be a big improvement but I can really understand people not using EF1 it if they are doing any complex server side processing.

    Tuesday, December 01, 2009 12:01 PM
  • Got it, I see what you are doing now. I am originally a database guy myself so the idea of even storing magic strings in the database is anathema to me.

    :) I hear you... except we needed a way to filter data in a multitude of ways.  So a user might want region A, B and D or maybe just A or maybe all regions that start with the letter A or are between B and E.  Multiply that by another half dozen filters and throw in a requirement that ALL the filtering be done in the database for direct reporting....  and you end up with magic strings.  I am sure there is a solution that is both elegant AND performant but this is what we came up with instead! :)

    Thanks for taking the time to give the input on this and other threads... your comments are quite helpful.

    Tuesday, December 01, 2009 12:20 PM

  • my concern is for people trying to load entities with an Invoke, then trying to bind that entity, edit that entity, and then expecting to be able to SubmitChanges for that entity. Those are the people who get hopelessly confused and get defensive when it is explained to them that they need to use a query to load the entity instead of the invoke.

    Pulling data from the server via queries makes perfect sense. Submitting changes to the server via a submit operation makes sense as well. What I miss is a way to transparantly do some work between showing fetched data and submitting changed data. So the natural solution would be to use the Invoke-operation, pass in the entities you need and have 'm merged transparantly on return. The argument of not supporting this scenario was:
    - the team couldn't guarantee the client side entity state when the server would massage the entities
    - performance might be an issue
    I don't see why these points wouldn't be an issue in any other WCF RIA scenario... When I check this forum I see several people used workarounds to achieve this goal anyway. So why not support it out-of-the-box with a specific method call?

     

    Tuesday, December 01, 2009 1:33 PM
  • @theo67:

    Wouldn't it be much better to just get the data you need, do the changes and then do the SubmitChanges? Why load entities, made specific changes to the entities, pass them down to a service operation, when you can do the changes on the client-side, and just call the SubmitChanges, or use Custom methods? The Service Operations is a way to let you do whatever you want, but not with entities that you have already loaded..if you do, make sure to Detach the entity from the DomainContext first to not add work to the UoW and disable the Dirty tracking etc.

    Tuesday, December 01, 2009 2:06 PM

  • Why load entities, made specific changes to the entities, pass them down to a service operation, when you can do the changes on the client-side, and just call the SubmitChanges, or use Custom methods?

    The scenario (or better said: scenarios) is like this:

    - user starts screen and enters some data
    - entities are pulled from the server
    - user changes some field, now we have dirty entities
    - user clicks something that requires a server side operation (business logic) to be invoked against the client side entities (context). Imagine you have a "distribute" button that distributes an amount over several entities and this distribution rule is (complex) server side logic (requiring database lookups).
    - entities are send to the server and manipulation operation is invoked. The client syncs its local state
    - UI is refreshed and operation is done
    - user enters some more data
    - user presses save, now I want to submit changes in a unit of work

    A concrete example:
    - user fetches an existing sales order
    - user adds an order line
    - user presses a recalculate button to recalculate the order discounts, shipment cost, etc
    - user looks at the changed order and submits the order when he's satisfied
    This "recalculate" is an optional operation based on the "richness of the application" ;-)

    So this middle piece can be anything you can imagine while looking/editing data (entities). The problem with the Custom-operation is it requires SubmitChanges as well and at that stage you're not willing to persist the changes.

    Does this make sense?

     

    Wednesday, December 02, 2009 7:15 AM
  • @Fredrik,

    I agree, most of the time, its much better to "just get the data you need, do the changes, and then do the SubmitChanges".

    However! I also agree with Theo, sometimes the "do the changes" part is significantly more work then some updates from the UI by the user. That doing this work makes more sense to do it on the server, rather then the client.

    In my case its rating an insurance policy. Specially quoting a policy without requiring the policy to be persisted to the DB.

    The insurance policy itself is an object graph composed of a Policy object, one or more Coverage objects, zero or more Endorsement objects, plus a plethora of support objects (Person, Address, etc...)

    "Rate" is a behavoir that logically makes more sense to do on the server, as it involves many & numerous DB lookups and in some cases some interesting calculations. Putting Rating on the server helps protects your IP (intellectual property), plus it avoids an extremely "chatty" conversation between the SL client and app server. (granted in either case there is still a lot of chatter between the DB & app server).

    My first thought when creating my Rate method was to pass a complete policy graph in as a parameter, and return a complete policy graph as a return value (based on normal WCF protocols). RIA July 2009 baulked at this. Yes a custom method helps, however custom methods imply you are going to persist the object graph; In the application I recently finished one of the requirements was quoting a policy without actually persisting the quote. We only persist issued policies.

    I wound up defining a Rate method that accepted an XElement and returns an XElement, where I serialize the policy to/from XML for the rating engine.

     Jay

    Wednesday, December 02, 2009 11:55 AM
  • I have always found your points interesting Theo, and I think you have a really important use case. My feeling has always been that this is a feature that doesn't fit into the V1 release of WCF RIA Services. If I was designing this featue (and I am not) one possibility would be to wait for the WPF version of RIA Services to be done first. The reason is that the WPF version of RIA Services would (theoretically) give me a DomainContext and RIA Services type entities within the Desktop CLR. So, that would make it possible for me to serialize the entire EntityContainer, ship it to the server, do whatever processing I want to do, and then send any modified Entities back to the client all without actually converting the entities back to the DAL types.

    Is that a good design? I have no idea, I just made it up. I am sure Nikhil will come up with a much better concept when they get to it. The point is, they will need to time to think about it, design different prototypes, try them out, and then come up with a sound technical design. It our role in this process to come up with well thought out use cases that show:

    1. That a need exists
    2. That Microsoft is the only and/or best one who to fulfill that need
    3. That the problem is "ripe"

    It is 2 and 3 that are the most tricky. For example, I have seen many requests for Microsoft to add some kind of official MVVM support to Silverlight. That violates both two and three. Two is violated because by its very nature there is nothing about MVVM that requires it to be embedded in thte framework. Three is violated because the MVVM is still evolving and there is very little agreement on a standard way of writing them. Heck, there is no agreement that there should be a standard way of writing them. In many, many ways asking Microsoft to implement a feature is like asking the Supreme Court of the United States to decide a case. First the district courts (i.e. the programmer in the trenches), then the appeals court (i.e. MVPs, forums, people creating Codeplex projects, Nikhil with Silverlight.FX, etc) have their try and then, finally, Microsoft will take a look at it.

    OK, that was a little long winded of a post. The point is, keep pushing it Theo, people are listening, and please don't get discouraged because you don't see instant results.

    Wednesday, December 02, 2009 12:53 PM
  • I can see your point now. Your scenario can be solved with RIA Services today, or WCF. As with several frameworks, there can be about 5-20% when a framework can't solve a problem, in this case some others solution needs to be used.

    Think of the DomainContext as the ObjectContext in Entity Framework or the DataContext in Linq to SQL, it loads the data based on a query and return it to us, it will also cache the data and have a unity of work etc. We can add, do changes and then submit the changes. The same with WCF RIA Services, so for specific cases as for the "Recalculate", you can just call a service operation (InvokeAtribute, not a custom operation) get the new results needed, update the sales order already fetched with the new data.. then the user can hit the save button to submit the changes.

    I think most of the scenarios can be solved, but there may be some special cases when it maybe can't (need to find that one first ;)).

     

    Wednesday, December 02, 2009 5:56 PM
  • @Fredrik & @Colin

    I think in most cases the question isn't "can the problem be solved?" but "how should the problem be solved?"  I think Colin made a great point about whether or not something should be included in the framework.  Just because my life would be made easier if the framework did something for me doesn't mean it would impact many others.

    My main concern here was that I wasn't using RIA properly.  Turns out I had the wrong idea about what problem RIA Services was solving.  My first thought was "cool... a fully configured WCF service for free!"  Using the [ServiceOperation] let me just bypass all the RIA goodies and do my own thing whenever I wanted to.  Loading the context and all that was just useful stuff that came along for the ride.

    Turning that viewpoint on it's head makes me do two things.  First, it makes me want to structure my SL app to take advantage of the RIA Service data model since it all "just works."  Second it forces me to open my thinking to other possibilities for solving problems outside of RIA. 

    RIA solves a very specific problem and it does so quite well.  For other problems I can turn to other solutions. 

    Wednesday, December 02, 2009 6:48 PM
  • The same with WCF RIA Services, so for specific cases as for the "Recalculate", you can just call a service operation (InvokeAtribute, not a custom operation) get the new results needed

    Great feedback guys.... and I agree we shouldn't ask for more than appropriate.

    One of the problems I have with the current Invoke-operation: when you pass in an Order entity I expect the associated Orderlines and change tracking information to be marshalled as well, just as transparent as when doing a submit changes. Today the associated Orderlines nor the change tracking information will be marshalled. I have tested it. So when I pass in an Order-entity, why does RIA decide to exclude the associated Orderlines? This is part of my contract, I never told the framework to exclude associations, so that doesn't make sense. And REST is REpresentational State Transfer after all with the emphasis on "state". Basically I would like to see support for "SubmitChangesAndInvokeMyOperation". Today "SubmitChanges" is bound to validate/save/custom operation and should be called "SubmitChangesValidateAndPersist". It shouldn't be too hard to map it to something else on the server, would it?

    So WCF RIA has this great change tracking mechanism, transport protocol and flexible server side storage mapping, but you're left on your own as soon as you want to send client side state to the server for doing something else than persisting the data. I mean there is much more in life than saving data. Wouldn't it make sense having support for these additional operations as well? The whole idea of an AppServer is to encapsulate business logic so it can be used by different types of "thin" clients. You can replicate business logic on the client if you like, but the only truth lives on the server.

    Imagine Entity Java Beans where the "entities" don't leave the AppServer. All state is on the server and you have this chatty interface. In this context it makes perfect sense to poke methods on entity graphs. Lessons has been learned from that, so we changed the AppServer from statefull to stateless. This means all state will be on the client. So when you want to invoke business logic in this environment, you start by passing in the context (state). This can be a single parameter, but in forms-based scenarios it means passing in the entity context. WCF RIA has decided to exchange the full entity context and invoke a single operation instead of doing individual calls to create/insert/delete methods with simple values types from the client.  

    Basically I'm asking for a way to pass the entity context to the server and have a real "custom operation", which can be called without implicit persistence of the entities. I expect a proper entity graph on the server as well. I don't see why this doesn't fit in the current WCR RIA stack.... the only difference with a custom operation is you're not persisting data, but you invoke some other operation. Why is the save so special? The actual persistence implementation is out of the WCF RIA scope anyway, because you can do anything you like during save when you override the domain service. I assume the "special" aspect of save is the implicite validation-step. But even validation has to be used in the context of the operation: validation for deleting entities would trigger a different ruleset than for updating an entity.

    We're one of these companies that can't exploit the Entity Framework and get all the persistence for "free", because we have an existing database schema and we have to support the "other" database provider as well. So life is already tougher for us ;-)

    I hope I didn't hijack this thread and change the direction of the conversation. If so, I'm sorry.

    Thursday, December 03, 2009 2:12 AM
  • I agree with almost everything except your point about REST. WCF RIA Services != REST.

    Thursday, December 03, 2009 8:03 AM
  • Distributing object is something people have tried so many times, but it always fails.. That is why some well known architects say "Don't distribute objects". Look at WCF, there is a reason why it sends a message, not an object graph; it's a reason why DCOM more or less failed. Why should you pass down a whole entity if you only want it to be marked "ready to deliver". In this case to increase performance and to not send to much data in a enterprise RIA, we simply send the Order ID and the status, nothing more, no reason to send the whole object. BUT! I like the support of loading objects, it will make it easy for us to gather the data we need in a nice structure.

    Here is an old blog post: http://weblogs.asp.net/fredriknormen/archive/2009/04/30/will-net-ria-services-be-the-silver-bullet.aspx

    Note: The blog post is based on a really early preview of the RIA Services, the new version have improved stuffs a lot, but skip the RIA thing, it's the story about distributing objects in general that may be interesting.

    People building enterprise RIA, should now about the complexity of building one (and managed to build one), and what kind of complexity RIA Services tries to solve, when they do, they know how to take the best benefit of RIA Services and use it in a correct way. They will also know when to not use it, and when to use other technoligies.

     

    Thursday, December 03, 2009 8:21 AM

  • Distributing object is something people have tried so many times, but it always fails.. That is why some well known architects say "Don't distribute objects". Look at WCF, there is a reason why it sends a message, not an object graph; it's a reason why DCOM more or less failed.

    DCOM is the same as EJB: the entities live on the server and you have a chatty interface plus you're bound to a specific server machine. The solution to that was the introduction of the Data Transfer Object: free the server and move the state around. Consequence: mismatch between the rich internal domain model inside the AppServer and "behaviorless data objects" traveling to the client. So we build this nice abstraction on top of our database schema, we get a nice domain model, we tear it down and send data back to the client. Somehow we have to reconnect this client side world to the server side world again. RPC was not the answer, message based request/response is. So now we have entered the message based world... and the goal of WCF RIA Services is to make it easy: have a look at the terminology used by Brad Abrams http://blogs.msdn.com/brada/archive/2009/03/19/what-is-net-ria-services.aspx when it was called .NET RIA Services.


    Why should you pass down a whole entity if you only want it to be marked "ready to deliver".

    Well, you're right, if all you wanted to do is to change an entity property, do it on the client. But an application is all about data transformations using rules. You fetch something from the database and once it has been loaded as an entity it becomes meaningful. So changing a flag from "1" to "0" is not the problem here, it's the rule that determines how this flag changes from "1" to "0". Now we're in a scary area, since why would you trust any changes done on the client at all? I mean I can fetch the order from the server, change some amounts, why would the server trust this changed data? But this is a side step... 


    In this case to increase performance and to not send to much data in a enterprise RIA, we simply send the Order ID and the status, nothing more, no reason to send the whole object. 

    You're absolutely right when the decision/rule works against the persisted state which can be fetched from the store by the service. But what if you need to see the changed state that lives on the client to make the proper decission. Imagine you get a discount of 10 percent if you order 50 pieces and 20 percent for 100+ pieces. So I have an orderline in the database for 50 pieces and on my client I added another orderline for an additional 1000 pieces. I definitly need to pass the changed orderline quantity if I want a correct discount percentage (1050 pieces). But how can the client be sure it passes enough context? Basically the service should expose a method to accept a complete order to recalculate the price. Now it gets interesting: there are two variations of the "calculate price":
    - one is basically a proposal during data entry
    - the other one is an overruling piece of logic when persisting the order

    People building enterprise RIA, should now about the complexity of building one (and managed to build one), and what kind of complexity RIA Services tries to solve, when they do, they know how to take the best benefit of RIA Services and use it in a correct way. They will also know when to not use it, and when to use other technoligies.

    Exactly. So if the goal of WCF RIA Services is to make distributed programming easier, let's do so. But we should always be aware what we send to the middle tier, the same as we should be aware what we pull from the database. Over the years I have used several technologies and this discussion reminds me of the Progress 4GL environment with it's AppServer and TempTable support. That 4GL environment used .NET DataSet like parameters to talk to their AppServer. Generalizing WCF RIA Services feels like exchanging DataSets compared to more strict contracts using plain vanilla WCF. Now I'm definitly off track ;-)

    Thursday, December 03, 2009 2:06 PM
  • "But how can the client be sure it passes enough context?"

    But is it the really the client that should have the responsibility to know that, just a thought..

    Here is how I should have solved the OrderLine problem:

    Load the order by using a Query operation

    add the orderline by using the .shared code feature.. The .shared code will have a AddOrderLine method "added" to the Order entity. This method will or may have information to perform the discount based on the Order's state. If not, and we need that information from the sever side before we do a submit changes, we can use a service operation, only pass the information needed to do the discount, return the new discount result.

    Update the Order with the new discount information.

    Do something more with the order if needed

    SubmitChanges

    Conflict handling if there was any conflics

    Re Load Order if needed, but at this moment the Order on the client should have the same info as the order on the server. 


    "and the goal of WCF RIA Services is to make it easy"

    Yes, but it's not a Silver bullet, it can't and will not solve every thing. It will not be suited for every app, and they don't say it's the Silver bullet or your have to use it to build RIA. It's the developers and the architects role to know when it can be used or not to be used, as with every framework and technologies. The Silver bullet will never exists.. but different ways to solve problems will exists.If But if you have find a way to solve something much easier, I know the RIA team is more than happy to hear about your suggestions and feedback.

    Thursday, December 03, 2009 2:52 PM
  • We are passing an entity inside the function RecordLinkClaim as a parameter  and loading data in DB and getting a string value. All this was done in a ServiceOperation.It was working fine. But now we have upgraded RIA service to WCF RIA Service so now as we are changing  [ServiceOperation] -> [Invoke] and we are getting an error given below.

     Error 63 Operation named 'RecordLinkClaim' does not conform to the required signature. Parameter types must be an entity type or one of the predefined serializable types. Axis.Web.WPF.ReClaims.

     

    PLEASE HELP!!!!!!!!! any help will be highly appreciated

    Tuesday, February 02, 2010 8:00 AM
  • If you are using the WCF RIA Services for VS 2008, you can't pass a entity to the Invoke operation, it will work with the VS2010 version.

    Tuesday, February 02, 2010 8:10 AM
  • Similar problem here. I was using ServiceOperation to do simple operations like "void GenerateTemplate(Guid key)". I guess now I have to use ordinary web services for all those calls?

    At the beginning I really liked RIA services, but now I slowly begin to dislike it...

    Tuesday, February 02, 2010 9:27 AM
  • Hmm, I read through this blog and still don't understand why my current impl is not working?

    Anyone can help?? http://forums.silverlight.net/forums/p/179234/403660.aspx#403660

    Wednesday, April 28, 2010 2:05 PM