I am new to WCF and am looking for some advice on a particular problem. I am using Enitity Framework and am wanting to return my entities as JSON through WCF. However I am only wanting to return certain information in certain circumstances. For example in one method I might want to return a users username along with their userid, in another instance I want to return a users username, userid and telephone number. Initially I thought maybe I could return an anonymous type such as
var obj = new { username = user.UserName, userid = user.UserId };
But after researching I found out that was not a good idea. I then thought of returning a Dictionary of key values, the problem with that approach is the JSON that is returned:
{"key":"username","Value":"Andrew"}
I am after something along the lines of
{"username":"Andrew"}
I have also though of making my own types. Is there a way to exclude properties? i.e. If my type has a property Telephone will I be able to exclude it in certain circumstances?
Any help / suggestions much appreciated
I know in DataContractSerializer, you can use EmitDefaultValue, for example, you can have a contract named UserInfo
[DataContract]
public class UserInfo
{
[DataMember]
public string UserID { get; set; }
[DataMember]
public string UserName { get; set; }
[DataMember(EmitDefaultValue=false)]
public int Age { get; set; }
[DataMember(EmitDefaultValue=false)]
public DateTime Time { get; set; }
}
I don't know whether EmitDefaultValue is supported by the JSON serializer, can you try it by yourself?
Related
In a class which needs to "contain information" about another class (sorry I don't know the terms for this), should I store the reference to that other class as something like an integer/id, or should I store it as an instance of the other class? What is this called, if there is a name for it?
As a very basic example, an app where we want to store what a user's favorite restaurant is:
public class User {
public int id { get; set; }
public string name { get; set; }
// id of restaurant...
// public int favoriteRestaurantId { get; set; }
// ...or entire instance of Restaurant type
// public Restaurant favoriteRestaurant { get; set; }
}
public class Restaurant {
public int id { get; set; }
public string name { get; set; }
}
Note: if you think this is off topic, please explain why this question would be allowed and is a highly rated/useful question, but mine is not: Interface vs Base class Or at the very least tell me what this is "called" so I can research it more myself. As far as I can tell from Stackoverflow's FAQ this question is on topic.
Your first variant
public int favoriteRestaurantId { get; set; }
only makes sense if you are only interested in the id and not the other attributes (name) of the restaurant object. Otherwise you will need some external container that stores all restaurant objects and have to search the container for the restaurant with the given id.
In your second variant
public Restaurant favoriteRestaurant { get; set; }
if you write
someUser.favouriteRestaurant = someRestaurant;
this also stores a reference to an existing someRestaurant. It will not copy the whole object. at least not in languages like C# and Java.
Only if you do something like
someUser.favouriteRestaurant = new Restaurant(someRestaurant);
the user will have its own copy of the restaurant object.
There are cases where this would make sense but in your example it is probably not a good idea for two reasons:
If for example the name of the someRestaurant changes, this should also change the name of favouriteRestaurant. This will not happen automatically if favouriteRestaurant is a copy.
It is a waste of memory.
Given a simple example as follows, I'd like some guidance on whether to store as a single document vs multiple documents.
class User
{
public string Id;
public string UserName;
public List<Post> Posts;
}
class Post
{
public string Id;
public string Content;
}
Once the data is stored, there are times when I will want all the posts for a given user. Sometimes I might want posts across multiple users that meet a particular criteria.
Should I store each User as a document (with Posts embedded), or does it make more sense to store Users and Posts as seperate documents, and have some sort of ID in my post to link it back to a User?
Now, what if each user belonged to an Organization (there will be hundreds of organizations in my application)?
class Organization
{
public string Id;
public List<User> users;
}
Should I then stay with the single document approach? In this case I would store one giant document for each organization, which will contain embedded users, which in turn contain embedded posts?
You should keep them as separate documents. User, Organization, and Post are great examples of aggregate entities, and in Raven, each aggregate is usually its own document.
Only entities which are not aggregates should be nested in the same document. For example, in Post you might have a List<Comment>. Comment and Post are both entities, but only Post is an aggregate.
You should instead model them with references:
public class User
{
public string Id { get; set; }
public string Name { get; set; }
public List<string> PostIds { get; set; }
}
public class Post
{
public string Id { get; set; }
public string Content { get; set; }
}
public class Organization
{
public string Id { get; set; }
public List<string> UserIds { get; set; }
}
Optionally, you can denormalize some of the data into your references where appropriate:
public class UserRef
{
public string Id { get; set; }
public string Name { get; set; }
}
public class Organization
{
public string Id { get; set; }
public List<UserRef> Users { get; set; }
}
Denormalizing the user's name into the organization document has the benefit of not needing to fetch each user document when displaying the organization. However, it has the drawback of having to update the organization document any time a user's name is changed. You should weigh the pros and cons of this each time you consider a relationship. There is no one right answer for all cases.
Also, you should be considering how data will be really used. In practice, you will probably find that your Organization class may not need a user list at all. Instead, you could put a string OrganizationId property on the User class. That would be easier to maintain, and if you wanted a list of users in an organization, you could query for that information using an index.
You should read more in the raven documentation on Document Structure Design and Handling Document Relationships.
I have WCF service that return Json.
Data contract defined below
[DataContract]
public class OptionData
{
[DataMember]
public string Book { get; set; }
[DataMember]
public string Id { get; set; }
[DataMember]
public string DealId { get; set; }
[DataMember]
public string DeliveryDate { get; set; }
[DataMember]
public string ExpiryDate { get; set; }
}
And Operation Contract defined as follows
[Description("Returns List of Options by user id")]
[WebGet(UriTemplate = "{sessionId}/Application/{applicationId}?start={start}&limit={limit}&page={page}", ResponseFormat = WebMessageFormat.Json)]
public List<OptionData> GetAllTask(string sessionId, string applicationId)
I need to add dynamically new DataMember field to the OptionData class .
What is the best practice to do it ?
As long as the client receiving the json knows how to handle dynamically added class members, you can use the Expando object strategy outlined in the accepted answer to this SO question. It uses the ServiceStack library but you may be able extract the necessary code to do what you want. A simple key/value pair approach from an ExpandoObject is documented in this code snippet.
EDIT: I should point out that this approach wouldn't rely on WCF so it may not be what you need given the context of the question.
If you know you want JSON, you could always control the serialization yourself (see this post) - just return a string of JSON using an existing library.
Another option is to just us IsRequired = false if you know all the possible field names.
The final alternative is to use the same pattern WCF uses for Forward-Compatible Contracts - just attach all unknown properties to single collection object (ExtensionData). ExtensionData is just a dictionary of key/value pairs according to this post. Unfortunately - ExtensionData is not writable directly. This would be my approach to simulate what IExtensibleDataObject is doing...
[DataContract]
public class OptionData
{
[DataMember]
public string Book { get; set; }
[DataMember]
public string Id { get; set; }
[DataMember]
public string DealId { get; set; }
[DataMember]
public string DeliveryDate { get; set; }
[DataMember]
public string ExpiryDate { get; set; }
[DataMember]
public Dictionary<string, string> Metadata { get; set;}
}
I don't think this is possible.
Let's think about what your DataContract is for a moment: it's how your service defines what it knows about - either as input or output. A client has to either find this out through meta-data exchange discovery or from a static proxy class (in a dll probably) that you provide.
If you change your contract on the fly, there's no mechanism for your service to let its clients know that the contract has changed. There's just no way to change that contract on the fly.
Even if you changed the definition of the class on the fly, including the proper attributes, etc, the client would not be able to find out about it since the contract had already previously been published.
I can't imagine what kind of mechanism would be needed to communicate changes like this on the fly with a client.
The only workaround I can think of is to have a parameter that takes in a string and allows clients to pass in XML or similar which could be just about anything. That's a pretty nasty hack though...
I just ran up against this exact issue as i posted recently here:
Configuring WCF data contract for proper JSON response
My solution was to use ExpandoObject. However, I had to use Newtsoft.json to do the JSON serialization then I had to make my webservice return raw text (rather than rely on the WCF serialization). I would be happy to post my code if you like. There may be a way to do dynamic datacontracts, but I wasn't able to figure that out. But my solution does the job.
If you need to dynamically control the data structures your RESTful service is returning, I think your only option is to return something like an XDocument. Your service operation could create an XDocument of an arbitrary structure and return that. That being said, I'm not sure what would happen when WCF tries to serialize an XDocument to JSON.
My entities look something like that (simplified):
public class Person
{
public Guid Id { get; set; }
public string Name { get; set; }
public IList<Department> Departments { get; set; }
}
public class Department
{
public Guid Id { get; set; }
public string Name { get; set; }
}
I'm querying the database through criteria api for all persons that have a department with a certain name that should match a like-pattern.
It happens that a person contains two or more departments whose names contain the same character sequence which is used by the query. Therefore the same person is returned multiple times. To surpress this, I know that I can use criteria.SetResultTransformer(Transformers.DistinctRootEntity); but this works only as long as the result is not paged.
When I'm paging the result I don't only need to get the first page but I also need to know how many entities there are in total. Unfortunately the result transformer does not work when calling criteria.SetProjection(Projections.RowCount()) as there is no result to be transformed.
Can I somehow avoid retrieving the whole list of person with the result transformer and then manually taking the right part out of the collection?
Best Regards
Oliver Hanappi
You need to include distinct in your sql request. Some information you can find here. Second answer mostly
I'm creating a WCF service that transfers entity objects created via entity framework. I have a User entity that maps to a User db table. There are certain User fields (Password, DateCreated, etc) that I don't want to expose to the client but, because they are non-nullable in the db, Visual Studio requires mappings. Setting these properties as private seems like a good workaround but these properties are converted to public when consumed by a client.
Is there a way around this, or a better approach to take? I'd rather avoid changing these fields at the db level just to make EF happy.
This sounds like to perfect opportunity to segregate the layers of the application. What you should do is create objects that are specific to the WCF layer that act only as Data Transfer Objects (DTO) to the outside consumers.
So, in your WCF service layer you make will your calls to your data access layer (Entity Framework) which retrieves User objects and you should return to your consumer objects constructed with only what you want to expose.
If you do this, you can explicitly control what you make visible to the outside world and also hide any implementation details about what you are doing from a data storage perspective.
As an extremely crude example, in your Entity Framework layer you might have this object:
namespace ACME.DataAccessLayer.Entities
{
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string Hash { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
}
namespace ACME.DataAccessLayer.Services
{
using ACME.DataAccessLayer.Entities;
public class UserService
{
public User GetUser(int id)
{
using (ACMEDataContext dc = new ACMEDataContext())
{
// psuedo code to return your user with Entity Framework
return dc.Users.FirstOrDefault(user => user.Id == id);
}
}
}
}
Then in your WCF later you might have an entity like:
namespace ACME.Services.DataTransferObjects
{
[DataContract]
public class User
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
}
}
Then you would expose a service endpoint that would return back the DTO as such:
namespace ACME.Services
{
using ACME.DataAccessLayer.Services;
public class PublicWCFService : IUserService
{
public ACME.Services.DataTransferObjects.User GetUser(int userId)
{
ACME.DataAccessLayer.Entities.User entityFrameowrkUser = new UserService().GetUser(userId);
return new ACME.Services.DataTransferObjects.User
{
Id = entityFrameowrkUser.Id,
FirstName = entityFrameowrkUser.FirstName,
LastName = entityFrameowrkUser.LastName
};
}
}
}
Now what you would do is just return the DTO object which will not have any of the attributes, or methods that you may have in the real entities you use in your system.
With this approach, you can safely break the layers of the application into different layers (DLLs) that can easily be shared and extended.
This is a quick example, so let me know if there's anything further that would make this example more clear.
You could always implement IXmlSerializable on the entity object. Then, you would be able to dictate the structure of what is sent to the client (the client would get a different representation, obviously).
Either that, or if you can, add the DataContract attribute to the type, and the DataMember attribute to only the properties you wish to send over the wire.