[DataContract()]
public class Contract
{
.........
Some Properties with DataMembers Attribute.
............
..............
[DataMember(Name = "FirstName")]
public string Name { get; set; }
}
I have above class and I have two web methods (operations)
In 1st web method I want to expose Name as FirstName and in 2nd web method expose Name as LastName.
I don't want to create separate data contracts.
Please tell me how to achieve this?
You can use reflection and change the value of the attribute at runtime depending on which method you in currently. Check out these links on StackOverflow:
How to set attributes values using reflection
Change Attribute's parameter at runtime
But I think the best way would be to either have 2 separate contracts or create a contract with both properties.
You can also implement a surrogate to special-case this type during serialization. As an example, see the Data Contract Surrogate sample.
Related
I've been writing a few customconverters, extending Newtonsofts JsonConverter and stumbled on a little problem. Say I have two properties on a class, but they cannot be the same value. Is it possible to find the value of another property in a converter... for example, say I have a model like so.
I'd want to be able to check the value of Surname in CustomCompareConverter to ensure its not the same value as Firstname
public class Person
{
[JsonConverter(typeof(CustomCompareConverter), "Surname")]
public string Firstname { get; set; }
public string Surname { get; set; }
}
```
You are trying to do multiple things with the json deserialization process that really should be separated
converting some external json into your domain object
validating the domain object.
The fact that the Surname cannot match the FirstName property is a business rule of your domain. So keep that within your domain. You can:
write a separate validator class that will check the state of your
person object and return a list of validation failures
implement IValidatableObject on your Person class and implement the
interface
write a custom validator like in this SO question
Use the JSON deserialization process as an anti-corruption layer to keep the details of external systems out of your your domain structure. Once you've take the extenal object and converted it to your domain object then use conventional means to validate that your domain object.
I have some DataContracts defined, one is inherited from the other. These are not the exact classes but there are something like this:
[DataContract]
public class BaseModel
{
[DataMember]
public String Id {get;set;}
}
[DataContract]
public class MyModel : BaseModel
{
[DataMember]
public String Name {get;set;}
}
I am using WCF with the basicHTTPbinding to move data from server to client. When I use fiddler to look at the data being sent it is doing something a bit strange.
In the raw data being returned, when I examine the Name property I can see 'Name' followed by the data. For the Id property I see 'Id http://schema.datacontract.org/2004/07/MyService' followed by the data. I only every see the schema.datacontract.org part for the fields from the base class. Why do only the inherited fields get that schema part? Both classes are in the same namespace. I don't want it on ANY properties as its adding significant size to my response. Is there anyway I can turn it off?
I changed each [DataContract] to include Namespace with the same value, e.g.
[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/MyCode.Service")]
and this has fixed my issue. Not sure why it needed to be specified since they were in the same namespace already but it does work.
I have a ServiceContract which returns dynamic type and looks like following:
public dynamic LoginViaOpenId(string openIdUrl)
The dynamic return type could be a DataContract that I have defined, or a string. But since I have not used my DataContract on the service, client does not know anything about it and cannot access it.
My DataContract is something like below:
[DataContract]
public enum OpenIdStatus
{
[EnumMember]
Authenticated,
[EnumMember]
Authenticating,
[EnumMember]
Cancelled,
[EnumMember]
Failed,
[EnumMember]
RedirectToLogon
}
I know if I had hierarchical types I could have used KnownType to conquer this, but am out of idea for this scenario.
Any idea?
A dynamic DataContract is an oxymoron. A DataContract is a predetermined and mutually agreed-upon data structure, and dynamic is an object whose structure is not predetermined and thus cannot be agreed-upon, since it can be anything.
It doesn’t appear you actually need to return a dynamic data type, but rather a varying data type. The difference is that a varying data type is one of a set of fixed data types, whereas a dynamic data type is one which does not have a predetermined structure. Since your return value is one of several knows shapes, there is no need to use the "shapeless" (or "freeform") dynamic type, which isn't supported by WCF.
Instead, you could have the [OperationContract] method return a type with a [DataContract] that will act as a wrapper object that has a single data member of type object, and use [KnownType] on the wrapper object to specify the possible types that may be returned inside the wrapper. Since everything inherits from object, there is already a hierarchy in place.
[DataContract]
[KnownType(typeof(OpenIdStatus))]
[KnownType(typeof(string))]
public class ReturnValue
{
[DataMember]
public object Value { get; set; }
}
I think that WCF is going to have issues serializing / deserializing your dynamic type. I would recommend that you set up a contract for the method return based on a defined interface. Alternatively, you could take responsibility for the serialization yourself and make your service return a string. The client will have to have knowledge of what type to de-serialize the string to. There is a similar question on this here:-
How to return dynamic List from WCF HTTP Service
In the benefit of creating clean decoupled code in c# I was hoping to get some feedback on using a dynamic parameter to construct objects. Typically I believe you'd create an interface and use the interface as the contract, but then you have to create interfaces for all your classes which I think is kind of icky...
So, my question is what are the pros and cons of doing something like this:
class Class1
{
public string Description { get; set; }
public string Name { get; set; }
public Class1(dynamic obj)
{
Name = obj.Name;
Description = obj.Description;
}
}
vs
class Class1
{
public string Description { get; set; }
public string Name { get; set; }
public Class1(IClass1 obj)
{
Name = obj.Name;
Description = obj.Description;
}
}
Pros of the interface:
The compiler will tell you if you're using the wrong kind of argument
The signature of the constructor tells you what's required from the parameter
Pros of dynamic:
You don't need to declare the interface or implement it
Existing classes with Name and Description properties can be used with no change
Anonymous types can be used within the same assembly if they have Name and Description properties
Personally I typically use C# as a statically typed language unless I'm interacting with something naturally dynamic (e.g. where I'd otherwise use reflection, or calling into COM or the DLR)... but I can see that in some cases this could be useful. Just don't over-do it :)
In both scenarios for the method to function properly as expected the objects being passed into the method must have your Name and Description properties.
My concern is that the best practice for using a dynamic as you have, you would need to provide additional method documentation to ensure other programmers or even yourself six months from now know the expected data contracts that must be present on the object being passed and even then you really should write error handling into your method to ensure it functions as expected when that contract is broken.
Does all these potential gotchas out weight the hypothetical gain of not writing an interface which in the example given would be literally only a 5 basic lines of code, which would then do everything your forcing yourself to do manually.
Assuming you want to follow best practices which lead to well documented and easy to read code. I would lean towards using an interface for this purpose.
I write a WCF service for Insert and delete operation here we used generic method but it gives following error
"System.Runtime.Serialization.InvalidDataContractException: Type 'T' cannot be exported as a schema type because it is an open generic type. You can only export a generic type if all its generic parameter types are actual types."
here "EntityBase2" is base class for all entities
[ServiceContract]
[ServiceKnownType(typeof(EntityBase2))]
public interface IBackupUtility
{
[OperationContract]
void Delete<T>(T entity) where T : EntityBase2;
[OperationContract]
void InsertORUpdate<T>(T entity) where T : EntityBase2;
}
Question is how i can expose generic type 'T'?
I think it is imposible, how could it generate the wsdl that way?
You have two options:
You could send the type as a parameter.
If you want to expose crud operations for entities I would recommend to use a code generator, maybe a T4 template for EF.
This post is old indeed, but maybe someone find this solution useful:
WCF and Generics
Answer to this question is both Yes and No. Yes for server prospective and No for client prospective.
We can create a generic Data Contract on server but while using that in any operation contract we have to specify a data type of the generic.
And at client end that data contract will be exposed only as a strongly data type not generic.
[DataContract]
public class MyGenericObject<T>
{
private T _id;
[DataMember]
public T ID
{
get { return _id; }
set { _id = value; }
}
}
[OperationContract]
MyGenericObject<int> GetGenericObject();
This is what we have in Server we can see while using generic data contract we have to specify the type otherwise it’ll give compile time error.
On client what we get from WSDL is a follow:
[DataContract]
public class MyGenericObjectOfint
We can see here what we get from WSDL is not a generic data contract WSDL proxy generate a class with a new name using some convention.
Convention used is
Generic Class Name + "Of" + Type Parameter Name + Hash
Hash is not always generated, it’ll be generated only when there is a chance of name collision.