I have such a contract:
[DataContract]
[KnownType(typeof(Person))]
public class Gadget
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public IPerson Person { get; set; }
}
It represents a gadget that belongs to a person. I just came up with this simple example, it's not important whether it makes sense or not.
So, instead of returning the Person class, I return the IPerson interface. Now the client can no longer generate a strong typed object, but will generate this:
public object Person { get; set; }
Now my question is: is it possible to let the client also generate the IPerson interface? It should have enough information, because it can only instantiate Person (only known type).
Interfaces will not be transfered by adding a service reference. These interfaces only exist in .NET, but your service is suppossed to be interoperable.
As far as your WSDL is concerned there is likely to be no way to tell Person and IPerson apart.
If you really want to use that interface you will need to move it across manually. This means editing the generated client code by hand.
Related
I feel like this should be really simple but I am having an issue figuring out what is going on. I am working with a WCF service and have "Reuse types in all referenced assemblies" on. I have some simple classes to transfer some data. The classes show up fine and all the basic members show up, but no methods do. Are methods not included in this? Do I have to specify this is what I want somehow? Here is some example code. I just switched out my names to make it a little more generic.
public class Car
{
public string CarColor { get; set; }
public string Model { get; set; }
public int Year { get; set; }
public string GenerateId()
{
return CarColor + Model + Year;
}
}
In this example I get CarColor, Model, and Year on the client side but not GenerateId.
So I ended up doing this a little different. It totally makes sense that only the data comes over. The problem is that I didn't want to have to have a new project to hold the data types. Its just a pain to have a new repository and a completely separate project for a handful of classes. Since I really only need the methods on the client side, I am just creating partial classes with them in it on the client side. That way I can pull the data structure from the service but still extend it to have the methods I need.
Service definition
public class Car
{
public string CarColor { get; set; }
public string Model { get; set; }
public int Year { get; set; }
}
Client partial class
public partial class Car
{
public string GenerateId()
{
return CarColor + Model + Year;
}
}
How to invoke three data contract objects and create it in a single object?
I have a data contract class like this
[Serializable]
[DataContract]
public class Address
{
[DataMember]
public long AddressId { get; set; }
}
another data contract class like
[Serializable]
[DataContract]
public class Email
{
[DataMember]
public long EmailId { get; set; }
}
another data contract class like
[Serializable]
[DataContract]
public class Phone
{
[DataMember]
public long PhoneId { get; set; }
}
Now i want to use the AddressId, EmailId, PhoneId in the same method.
How it is possible??
Please, keep the [DataContract] attrubute only, you don't need decorating with Serializable as well.
Well, one have the following options with WCF Data Contracts:
Composite Data Contracts.
Member fields of any class marked as DataMember can be data contracts themselves, once they're decorated with DataContract attribute too. Aggregation of all nested data contracts illustrates the fact that data contracts are recursive in nature. WCF detects all the data contract enabled properties in the object graph and captures their state as well.
[DataContract]
class Address
{
[DataMember]
public long AddressId { get; set; }
}
// The same for the rest two, and then an aggregating type.
[DataContract]
class Contact
{
[DataMember]
public Address Address {get;set;} // here we go
[DataMember]
public Email Email {get;set;}
[DataMember]
public Phone Phone {get;set;}
}
Data Contract Hierarchy
Your data contract class may be a subclass of another data contract class, here you just have to explicitly opt-in for a given data contract, i.e. specify the DataContract on each type in the hierarchy tree.
[DataContract]
class ContactDetails
{
[DataMember]
public long AddressId { get; set; }
// you could move the phone and email details here too.
}
[DataContract]
class Contact : ContactDetails
{
[DataMember]
public string Name { get; set; }
}
You can't have three separate classes for each one and inherit from them at once in .Net. And my suggestion is the first case for you - that is data contract aggregation.
Bonus: Polymorphic Type Reference.
Applying the [KnownType(Type type)] attribute on a base type for passing polymorphic objects as operation contract arguments. This is definately not your case.
Contracts applied to classes to provide service metadata for your service (service class just can use decorated classes as parameter types in service methods). So - if you want to compose some type (class) from existing properties - this is not related to WCF contracts.
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.
I've seen this (unanswered) question asked once before, but in a different context. I'm looking to have two domain objects map to the same table, WITHOUT a discriminator. The two classes are:
public class Category
{
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
public virtual ReadOnlyCategory ParentCategory { get; private set; }
}
and
public class ReadOnlyCategory
{
public virtual int Id { get; private set; }
public virtual string Name { get; private set; }
public virtual ReadOnlyCategory ParentCategory { get; private set; }
}
The main difference is that all public properties of ReadOnlyCategory are read-only. My idea here is that I want all users of this class to know that they should only mess with the category they are currently 'looking' at, and not any other categories in the hierarchy. (I've left off other properties regarding the subcategories.)
Clearly, in the database, Category and ReadOnlyCategory are the same thing, and NHibernate should treat them very similarly when persisting them. There are three problems wrapped into one here:
1) How do I do the mapping?
2) When instantiating the objects, how do I control whether I instantiate Category or ReadOnlyCategory?
3) When persisting the objects, will the mapping be smart enough, or do I need to use an extensibility point here?
Any pointers on how I can get this to happen?
(Or am I crazy?)
This looks like wrong object model design to me. I don't see a good reason to introduce a new class just for authorisation reasons (whether user allowed to modify a given category object?). You may as well use one class and throw for example InvalidOperationException if an end user is not supposed to modify a category.
Which entity FluentNHibernate uses as entity
I create some entity in Domain(or BLL), such as the following:
public class Role
{
public long ID { get; protected set; }
public string Name { get; set; }
public string Description { get; set; }
public List<User> Users { get; set; }
public Role()
{
Users = new List<User>();
}
}
And I want make use of FlunetNHibernate to map them, but get errors:
The following types may not be used as proxies:
Freeflying.Domain.Core.Profile: method get_ID should be 'public/protected virtual' or 'protected internal virtual'
Yes, I recall the programmer requirement when use FluentNHibernate, the entity should be like this:
public class Role
{
public virtual long ID { get; protected set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
}
But It looks wired. Do you think so? How do you do when using FluentNHibernate? I don't want go back to Domain layer and add virtual for every property.
This is a basic requirement for using NHibernate; It allows NHibernate to generate a proxy class that descends from your class for lazy loading and such.
I have not seen a method of removing this requirement, though if such a thing is possible it would mean that you could not use lazy loading of objects and/or properties.
Here's a blog post that explains this a bit more; It also offers a way to avoid marking your properties as virtual, although I would really recommend that you do not use this method (marking classes to avoid lazy loading) as the benefits of lazy loading in most circumstances far outweigh the cost of making your properties virtual.