Lightswitch with WCF RIA Services datasource - Query operation [operation name] could not be found on the service - wcf-ria-services

I have built out my Lightswitch app to use a WCF RIA Services data source. I was able to reference my RIA Service project, and import the data types. However, any call to the service results in a "Query operation [operationname] could not be found on the service".
The real scary thing is that I have not found a hit in the search engines for this error - so I must be doing something VERY wrong.
The method signature looks like this:
public IQueryable<md_SKURevMngtRRPPhantom> GetRRPPhantoms(string site, string category, long? segment, DateTime? entryDate){
//implementation here
}
I have used Fiddler to see the call being made to the service...it looks like this:
http://localhost:26132/RevMngtDomainServiceData.svc/GetRRPPhantoms()?site='610'&category='B'&segment=5L&entryDate=datetime'2013-07-04T00:00:00'
Even a parameterless request to the default service method returns the same error.
This default request is defined as follows:
[Query(IsDefault = true)]
public IQueryable<md_SKURevMngtRRPPhantom> GetAllRRPPhantoms(){
///implementation here...
}
How can my Lightswitch project correctly import the WCF RIA Service as a datasource, and yet calls to the same service return "Query operation [operation name] could not be found on the service."?

It turns out I was indeed doing something very wrong...the md_SKURevMngtRRPPhantom object that I was returning, was an object defined in the Lightswitch project's DataSource that I was adding a property to by creating a partial class of it in my DomainService project. Seems this was a bad idea.
I changed the DomainService project to return a newly-defined class instead of a the md_SKURevMngtRRPPhantom class, and all worked fine.

Related

No event context active - RESTeasy, Seam

I'm trying to add a RESTful web service with RESTeasy to our application running on JBoss 7.x, using Seam2.
I wanted to use as little Seam as possible, but I need it for Dependancy Injection.
My REST endpoints are as follows:
#Name("myEndpoint")
#Stateless
#Path("/path")
#Produces(MediaType.APPLICATION_JSON+"; charset=UTF-8")
public class MyEndpoint {
#In private FooService fooService;
#GET
#Path("/foo/{bar}")
public Response foobar(#CookieParam("sessionId") String sessionId,
#PathParam("bar") String bar)
{ ... }
}
I'm using a class extending Application. There is no XML config.
I can use the web service methods and they work, but I always get an IllegalStateException:
Exception processing transaction Synchronization after completion: java.lang.IllegalStateException: No event context active
Complete StackTrace
I did try everything in the documentation, but I can't get it away. If I leave out the #Stateless annotation, I don't get any Injection done. Adding #Scope doesn't do jack. Accessing the service via seam/resource/ doesn't even work (even without the Application class with #ApplicationPath).
It goes away if I don't use Dep. Injection, but instead add to each and every method
fooService = Component.getInstance("fooService");
Lifecycle.beginCall();
...
Lifecycle.endCall();
which isn't really a good solution. Nah, doesn't work either...
I have resolved the issue. For some reason (still not sure why, maybe because I tried to use Annotations and code exclusivly and no XML config), my REST service was availiable under a "non-standard" URL.
Usually it'd be something like "/seam/resources/rest".
Anyway, if you have a "custom" path, Seam doesn't know it should inject a context. You need to add <web:context-filter url-pattern="something" /> to your component.xml.
Specifically we already had this tag, but with the attribute regex-url-pattern and I extended it to match the REST URL.

WCF with IOperationInvoker using Entity and Ninject

I have a WCF Service from which I need to log the calls to its methods. For this, I used this solution to be able to track the calls and call my internal audit service, which uses Entity 5.1 and injects the services/repositories/DbContext using Ninject.
My Invoke method looks like this:
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
var methodParams = (instance).GetType().GetMethod(_operationName).GetParameters();
var parameters = new Dictionary<string, object>();
for (var index = 0; index < inputs.Length; index++)
parameters.Add(methodParams[index].Name, inputs[index]);
_auditService.TrackFilterParametersValues(_operation.Parent.Type.FullName, _operationName, _operation.Action, parameters);
return _baseInvoker.Invoke(instance, inputs, out outputs);
}
In my Ninject module I have the internal stuff registered like this:
Bind<IAuditService>().To<AuditeService>().InRequestScope();
Bind(typeof(IRepository<>)).To(typeof(Repository<>)).InRequestScope();
Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
Bind<DbContext>().To<MyEntities>().InRequestScope();
Problem comes up when, inside the Repository, I call the dbContext to add the new Audit object like this:
_dbContext.Set<T>().Add(entity);
It errors out claiming that the DbContext has been disposed.
What would be the correct way of registering the DbContext on a WCF Service so it gets registered for an IOperationInvoker??
I have to mention that I have all this declaration the same for the main site I'm feeding up with this backend in MVC4 and it works perfectly (no WCF there). So I'm pretty sure something is needed to be corrected for the WCF lifetime cycle, but not so sure about what.
I found the reason of why this was behaving so nasty: in the chain formed by the IOperationInvoker, IOperationBehavior and IServiceBehavior, I was injecting the AuditService by the constructor of the first 2 of them, but in the latest (IServiceBehavior), since I was decorating the WCF class with it and couldn't overload the constructor, I was using the DependencyResolver to obtain the AuditService with a property like this:
public IAuditService AuditService
{
get { return DependencyResolver.Current.GetService<IAuditService>();
}
Then, when I started to debug, I noticed that the constructors were called when the WCF Test Client was querying the WCF for the WSDL data, but the Invoke method was never called because no web method was being invoked. So the AuditService instance (and DbContext) was all fine during the calls of the constructors, but by the time of invoking a web method and calling the Invoke method of the IOperationInvoker, the DbContext was already disposed long time ago.
My workaround for this was to delete all the references to the AuditService from all constructors and move the property with the DependencyResolver from the ServiceBehavior to the IOperationInvoker implementation. Once I did this, the AuditService is called right when it's needed, never before, and its DbContext is never disposed.
If MyEntities inherits from DbContext, then this should work:
Bind(typeof(DbContext)).To(typeof(MyEntities)).InRequestScope();

JAX-RS generic response and interface proxy

is there any way how to return generic describing entity type with the JAX-RS Response? Something like REST-Easy ClientReponse but JAX-RS standard and not implementation-specific class.
The thing is I want to call my REST service via its shared interface (created by some proxy provider) and returning only object does not allow add information I need. E.g. for creating resource via POST, I would like to return also URL to newly created resource and so on. Returing simple Response does not show what type of entity is stored within such response.
Response<MyObject> getMyObject(#PathParam("id" Integer id)
So far it seems that I will have to return simple Response and then create adapter which will simply call Response.getEntity(.class)
There is probably no such option...
GenericEntity allows you to return a generic. The actual type is held at runtime by GenericEntity, allowing the object to be serialized.
Here's a contrived example of how it can be used.
GenericEntity entity = new GenericEntity<Employee>(new Employee());
return Response.ok(entity).build();

RIAServices unsupported types on hand-built DomainService

My EF model was generated from my SQL Server database. I then generated a DomainService for RIAServices against the EF model. One of the entities is called "EntryCategories". The DomainService created this method:
public IQueryable<EntryCategories> GetEntryCategoriesSet()
{
return this.Context.EntryCategoriesSet;
}
Since my user interface display model looks quite different from the physical model, I decided to write my own DomainService for that and related entities. Yes, I know we are meant to modify the generated one but it has so much stuff in there and I wanted to focus on a small thing.
I removed the EnableClientAccess attribute from the generated DomainService and added a new class called ClientDomainService, and encapsulated in it the generated DomainService:
[EnableClientAccess()]
public class ClientDomainService : DomainService
{
// the generated domain service encapsulated in my new one.
private DataDomainService _dcds = new DataDomainService();
// reimplement one of the DataDomainService methods
public IQueryable<EntryCategories> GetEntryCategories()
{
return (from t in _dcds.GetEntryCategoriesSet() where t.EntryCategoriesVersions.EntryCategoriesVersionId == datahead.EntryCategoriesVersions.EntryCategoriesVersionId orderby t.DisplayOrder select t);
}
}
The very fist thing I tried is to reimplement the GetCateogoriesSet method but with the underlying data filtered based on another entity in my class (not shown). But when I build this, an error shows up:
Entity 'DataProject.Web.EntryCategories' has a property 'EntryCategoriesVersionsReference' with an unsupported type
If I comment out my CientDomainService, replace the EnableClientAccess attribute on the generated DomainService, and place the analagous linq filtering in the original GetEntryCategoriesSet method, the project compiles with no errors.
What is so special about the generated DomainService that my new one doesn't have? Is it that metadata.cs file?
What's special about the generated domain service is not the .metadata.cs file (you can keep it, and use it, but it doesn't solve your problem).
The problem appears somehow because RIA services (?) needs a 'domain service description provider' for the exposed Linq to EF entities. The LinqToEntitiesDomainService class has the LinqToEntitiesDomainServiceDescriptionProviderAttribute, already applied, so the generated domain services which inherit from it also inherit the provider.
When you build your own custom domain service, derived from DomainService, and expose entities through it, you need to apply this attribute yourself. Furthermore, since the provider cannot infer the object context type from the domain service base class (which it can and does if the base class is LinqToEntitiesDomainService), you need to specify the object context type in the attribute constructor, like this:
[EnableClientAccess()]
[LinqToEntitiesDomainServiceDescriptionProvider(
typeof(YourObjectContextType))]
public class ClientDomainService : DomainService
{
...
}
That should fix it.
Note that this means if you had hoped to abstract your object context away from your domain service, you'll be disappointed. I had opted for the seemingly popular repository model where all code that operates on the object context goes into a provider used by the domain service. This facilitates unit testing, but evidently doesn't remove the domain service's dependency on the object context. The context is required for RIA Services to make sense of your entites, or at least those referenced by the domain entity (such as EntryCategoriesVersions in your case).
If you want to expose a specific entity on a domain service you will have to provde at least one query method for it. This is also required when the entity is only accessed as a child of another entity.
In this case you need to add the EntryCategoriesVersions entityset to the domain service, to get the scenario working correctly.
What type is EntryCategoriesVersionsReference ? Try adding a [DataContract] annotation against the type, and appropriate [Key] and [DataMember]. It should help with marshalling.
For me, the fix for this error was to add a default constructor to the return type.
In OP's example, the property 'EntryCategories.EntryCategoriesVersionsReference' needs to be of a type with a default constructor.

Cannot expose service method in ADO.NET data service

I am trying to create a method that can be exposed through an ADO.NET data service. No matter what I do, the client cannot see the method that I am exposing. I am out of ideas. Please help:
[WebGet]
public ObjectResult<Product> GetAllProducts()
{
ProductOrdersEntities entities = new ProductOrdersEntities();
return entities.GetAllProducts();
}
I have also kept access open to the methods:
public static void InitializeService(IDataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
}
Still, when I create a client proxy, it cannot see the method GetAllProducts().
I was told by a developer in the Astoria team that the current code generation tool does not support generating code for service operations. By that time I had already started using the .Execute method to make an explicit HTTP request to invoke the method, and this strategy works fine; just that it is not elegant or typesafe.