I'm building a Silverlight MVVM template and and am getting stuck with the WCF Service returning and Entity Object.
Here's what I did:
Using Entity Framework on the server side
Created a small test database with a couple of tables.
Created a WCF Service on the server side
I then created a small test method returning an integer.
On my client side, I added a service reference and I receive the integer result in my completed method successfully
then changed my test service method to return a "Person" object (which is an Entity from Entity Framework)
updated my service reference and then it doesn't work!
I then the return type to any basic CLR Type and it works again
I checked Fiddler and I get the following 504 error in my service response:
HTTP/1.1 504 Fiddler - Receive Failure
Content-Type: text/html; charset=UTF-8
Connection: close
Timestamp: 08:56:23.783
[Fiddler] ReadResponse() failed: The server did not return a response for this request.
After trying to figure this out, I came across WCF Trace Logging and found this error:
There was an error while trying to serialize parameter :BasicResult. The InnerException message was 'Type 'MVVMProject.Web.DataSource.Person' with data contract name 'Person:http://schemas.datacontract.org/2004/07/MVVMProject.Web.DataSource' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.
I don't understand why this is so difficult? Must I set some property on my Entity to make it serializable? If I look at the Entity Framework's designer.cs file, I see a Serializable attribute on the Entity. Surely this means I can pass this via the WCF Service??? I don't understand this error, unfortunately...
Is it even possible to use Entity Framework with WCF Service?
Any help would be greatly appreciated.
I had same problem, it seams that the DataContractSerializer has a problem with the navigation properties of ef objects.
In my test project, I'm using the northwind database. I wanted to test the CodeFirst approach with the recommended DbContext.
The provided navigation properties are virtual and they are loading on demand, but the ef just return with the first level of the entity on navigation properties is filled.
On serializing the entity object the DataContractSerializer failed because the entity object is no longer bound to the DbContext and the serialization of the navigation properties failed.
This is happen when I try to consume a NW Employee object over my wcf service.
My soultion is to copy all data in a new object with the data contract attributes!
the service call:
public IEnumerable<EmployeeWcf> GetAll()
{
IEnumerable<EmployeeWcf> result = null;
result = from e in context.Employees.OrderBy( e => e.LastName )
select new EmployeeWcf
{
EmployeeId = e.EmployeeID,
Firstname = e.FirstName,
Lastname = e.LastName
};
return result;
}
the class:
[DataContract]
public class EmployeeWcf
{
[DataMember]
public int EmployeeId { get; set; }
[DataMember]
public string Firstname { get; set; }
[DataMember]
public string Lastname { get; set; }
}
This work but it seems to me that this is not a perfect solution.
I hope this helps you.
Related
I'm trying the built-in Authentication of ServiceStack. My approach is 'OrmLiteAuthRepository' so users' information are stored in Sql Server instead of the default in memory storage. I use Postman to test the endpoints.
My target is receiving user rows, updating user information, creating users, deleting an user row. Those are the endpoints I found in Postman after importing (I didn't create those endpoints):
GET 'http://localhost:47391/api/register',
PUT 'http://localhost:47391/api/json/reply/Register'
POST 'http://localhost:47391/api/json/reply/Register'
I tested POST, Sql Server automatically created the tables to store user data. And the data could be written into Sql Server so I have no problem with POST.
But with PUT, isn't it for updating the existing row? I append '/{id}' to the end. But it created a new row in the database instead of updating the existing one. How does it work?
With GET, I got no implementation error.
{
"ResponseStatus": {
"ErrorCode": "NotImplementedException",
"Message": "Could not find method named Get(Register) or Any(Register) on Service RegisterService",
"StackTrace": " at ServiceStack.Host.ServiceExec`1.Execute(IRequest request, Object instance, Object requestDto, String requestName)\r\n at ServiceStack.Host.ServiceRequestExec`2.Execute(IRequest requestContext, Object instance, Object request)\r\n at ServiceStack.Host.ServiceController.<>c__DisplayClass11.<>c__DisplayClass13.<RegisterServiceExecutor>b__10(IRequest reqCtx, Object req)\r\n at ServiceStack.Host.ServiceController.ManagedServiceExec(ServiceExecFn serviceExec, IService service, IRequest request, Object requestDto)\r\n at ServiceStack.Host.ServiceController.<>c__DisplayClass11.<RegisterServiceExecutor>b__f(IRequest requestContext, Object dto)\r\n at ServiceStack.Host.ServiceController.Execute(Object requestDto, IRequest req)\r\n at ServiceStack.HostContext.ExecuteService(Object request, IRequest httpReq)\r\n at ServiceStack.Host.RestHandler.GetResponse(IRequest request, Object requestDto)\r\n at ServiceStack.Host.RestHandler.ProcessRequestAsync(IRequest httpReq, IResponse httpRes, String operationName)"
}
}
How to implement it? I assume I consider the user a normal Web Service entity? and create 'UserService', and requests like:
[Route("/register")]
public class User : IReturn<UserResponse>
{
...
}
BUT there isn't a model class like 'User' due to the tables are created by ServiceStack itself, how to solve this?
Or is there something I am not aware of. Thanks.
The error message:
Could not find method named Get(Register) or Any(Register) on Service RegisterService
Is saying you're trying to call the built-in ServiceStack Register Service instead of your Service. But the Register Services isn't enabled by default, your AuthFeature likely explicitly enables it, either with:
Plugins.Add(new RegistrationFeature());
Or on the AuthFeature:
Plugins.Add(new AuthFeature(...) {
IncludeRegistrationService = true
});
If you don't want to enable ServiceStack's built-in Register Service you'll need to remove the registration where it's enabled.
If you instead want the Register Service registered at a different path, you can specify a different route with:
Plugins.Add(new RegistrationFeature {
AtRestPath = "/servicestack-register"
});
We have some custom collections such as this:
[Serializable]
public class OccupationCollection : Collection<Occupation>
{
}
We use these in objects like the following:
private OccupationCollection _occupations;
public OccupationCollection CurrentOccupations
{
get
{
if (this._occupations == null)
return new OccupationCollection();
else
return _occupations;
}
}
Now we are making a call to a WCF service, passing objects that contain these type of lists. The lists always end up being null in the service.
I'm pretty sure this has somthing to do with serialization or something like that.
What would the simplest solution that would require minimal changes to the existing objects to get this to work?
Have you hosted your service over HTTP?
If yes, can you use fiddler to check the HTTP traffic and confirm whether serialized version of the parameter is being sent across the wire? If yes, there can be a parameter mismatch in contract between server and client.
Also is the object holding OccupationCollection decorated with Serializable/DataContract attribute? If you have DataContract attribute, ensure that the properties that need to be serialized are marked with Datamember attribute.
More details out here..
http://blog.functionalfun.net/2009/09/if-your-wcf-service-is-unexpectedly.html
All of my data contract objects in my service inherit from BaseMessage...
[DataContract(Name = "BaseMessage", Namespace = "http://www..."]
public class BaseMessage
{
[DataMember]
public Guid MessageId { get; set; }
}
I am familiar with using Message Inspectors to look at the actual SOAP payload that goes across the wire. However, what I want to do is to somehow hook into the message pipeline to do the following:
Look at an incoming message and read out of it the MessageId field ideally without searching the whole string message object for a string match - unless there is a fast way to do this.
Extract out of a message the MessageId with a view to creating a header inside the message containing the MessageId. Again I dont really want to search the whole message for the a string match.
I am familiar with using IClientMessageInspector and IDispatchMessageInspector to look at the messages, but I think at this point in the pipeline I dont have access to the actual object to access its fields.
Thanks
If you want to determine what members go in the body of the message versus its headers, you need a message contract.
I have web services written on WCF. I use request/response pattern and don't use FaultException. I return an error code in response contract as string. I need to expose error codes for clients in order to clients can handle exceptions.
For example:
Var r = client.DoSomething();
Switch (r.ErrorCode)
{
Case ERROR_CODES.SomeCode:
//TODO:
}
Clients are WS-*, not only .Net.
UPDATE:
Sorry, my English is elementary. I've tried to explain in a different way.
When I use class File, I know that this class can throws some exceptions, for example, FileNotFoundException or DirectoryNotFoundException. If I create a File service How can I tell client that my service can returns "FileNotFound" or other error codes?
We generally try and use FaultContracts.
When we cannot we use a Response object that inherits from ResponseBase. ResponseBase has 2 properties, StatusCode and StatusMessage.
In your case ErrorCode, just add this property to your data contract.
I am trying to build a WCF DataService on top of a Code Only DbContext. However as soon as I add the first DbSet property to my DbContext I get "Request Error" when accessing the .svc.
All I need to get the error is to have this DbContext:
public class JukeboxContext : DbContext
{
public DbSet<Song> Songs { get; set; }
}
and then do a basic WCF DataService based on it, and the error happens when i run the service.
Any ideas on what I need to do?
Turnes out the exception means that it can't resolve which field is the primary key.
The easy way to go is to name it ID or ID - otherwise the DataServiceKey attribute will let you use composite keys