DataContract composite Class - wcf

I have a problem with serialization composite class (using WCF Service).
here my class in namespace1 (it is not in service namespace) :
[DataContract]
public class UpData
{
[DataMember]
public double Version ;
public UpData()
{
this.Version = -1;
}
}
In my Service namespace (in interface) I deсlare this procedure :
ArrayList GetDownloadPath(Dictionary<string,string> lib1, Dictionary<string,string> lib2);
ArrayList contains UpData objects.
I have error(
How will be right to send ArrayList of UpData objects? (may be specific DataContract?)
Thanks a lot!

I'm not sure if ArrayList is serializable by default. Using a generic list could solve your problem:
[OperationContract]
List<UpData> GetDownloadPath(Dictionary<string,string> lib1, Dictionary<string,string> lib2);
EDIT: I think you also need to specify a getter and setter for your Version property, i.e.
[DataContract]
public class UpData
{
[DataMember]
public double Version { get; set; }
public UpData()
{
this.Version = -1;
}
}
More info here.

Related

Cannot create a DbSet for 'Model' because this type is not included in the model for the context

I do a Generic and using DI
so I create a empty class
public class DBRepo
{
}
and my model class to inheriting class DBRepo
public partial class UserAccount : DBRepo
{
public int Id { get; set; }
public string Account { get; set; }
public string Pwd { get; set; }
}
then this is a Interface to do CRUD
public interface IDBAction<TEntity> where TEntity : class,new()
{
void UpdateData(TEntity _entity);
void GetAllData(TEntity _entity);
}
public class DBService<TEntity> : IDBAction<TEntity> where TEntity : class,new()
{
private readonly CoreContext _db;
public DBService(CoreContext _db)
{
this._db = _db;
}
public void UpdateData(TEntity _entity)
{
this._db.Set<TEntity>().UpdateRange(_entity);
this._db.SaveChanges();
}
public void GetAllData(TEntity _entity)
{
var x = this._db.Set<TEntity>().Select(o => o).ToList();
}
}
And I Dependency Injection Service Provider in constructor
this.DBProvider = new ServiceCollection()
.AddScoped<IDBAction<DBRepo>, DBService<DBRepo>>()
.AddScoped<DBContext>()
.AddDbContext<CoreContext>(options => options.UseSqlServer(ConnectionString))
.BuildServiceProvider();
last step I Get Services
DBProvider.GetService<IDBAction<DBRepo>>().GetAllData(new UserAccount());
I will get a error message same with title
or I change to
DBProvider.GetService<IDBAction<UserAccount>>().GetAllData(new UserAccount());
I'll get other message
Object reference not set to an instance of an object.'
but the void UpdateData() is can work,
so how to fix GetAllData() problem?
The error simply is because the class you're using here UserAccount has apparently not been added to your context, CoreContext. There should be a property there like:
public DbSet<UserAccount> UserAccounts { get; set; }
Regardless of whether you end up using the generic Set<T> accessor, you still must defined a DbSet for the entity on your context.
That said, you should absolutely not be creating your own service collection inside your repo. Register your context and your repo with the main service collection in Startup.cs and then simply inject your repo where you need it. The DI framework will take care of instantiating it with your context, as long as you have a constructor that takes your context (which you seem to).
And that said, you should ditch the repo entirely. It still requires a dependency on Entity Framework and doesn't do anything but proxy to Entity Framework methods. This is just an extra thing you have to maintain and test with no added benefit.

Protobuf type inheritance with WCF

We have trouble with the protobuf-net type inheritance.
We have a base class like this:
[DataContract, ProtoContract]
public abstract class BaseClass : IBase
{
protected IBase()
{
RequestUID = Guid.NewGuid();
}
[DataMember(Order = 8000), ProtoMember(8000)]
public Guid ID { get; set; }
[DataMember(Order = 8001), ProtoMember(8001)]
public string User { get; set; }
}
And classes which inherits from BaseClass.
[DataContract, ProtoContract]
public class ConcreteClass : BaseClass
{
[DataMember(Order = 4), ProtoMember(4)]
public int? WorkItemId { get; set; }
}
(In future we are going to use only ProtoMember and ProtoContract.)
When the client and server starts we do following in both environments:
RuntimeTypeModel.Default[typeof(BaseClass)].AddSubType(50, typeof(ConcreteClass));
Now when we pass an instance of ConcreteClass to a WCF service operation we get exceptions:
BaseClass does not provide a public constructor. (Wrong type chosen for deserialization)
Or if we provide a public constructor for BaseClass it tries to cast the BaseClass object to ConcreteClass on the server. (Again wrong type)
And under some special circumstances (we don't know exactly when this happens) Protobuf tries to deserialize from OtherConcreteClass to ConcreteClass.
What are we doing wrong? The WCF behavior is register correctly. We had no problems with simple classes (no inheritance).
Is there and documentation how two configure the inheritance properly for WCF scenarios?
Thanks

serialize an interface wcf

I have an interface, called IDeviceConfig, as follows:
[KnownType(typeof(Device))]
[KnownType(typeof(DeviceGroup))]
[DataContract()]
public interface IDeviceConfig
{
[DataMember()]
string Name { get; set; }
[DataMember()]
List<Property> Properties { get; set; }
ActionResult PerformAction(string ActionId);
}
The interface will be implemented by two classes, as follows:
public class Device : IDeviceConfig
{
...
}
public class DeviceGroup : IDeviceConfig
{
...
}
In my WCF service, I need to return a list of IDeviceConfigs; when I decorate the interface with KnownType, Visual studio complains saying that Attribute 'KnownType' is not valid on this declaration type.
Can someone please explain how to return a list of IDeviceconfigs?
If you look at the definition of KnownTypeAttribute, you cannot apply to Interfaces.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = true, AllowMultiple = true)]
public sealed class KnownTypeAttribute : Attribute
"Known types can be associated only with classes and structures, not interfaces." from here:
http://msdn.microsoft.com/en-us/library/ms730167.aspx

Common WCF Response Handler?

I have a WCF Client, and the Endpoint has just been upgraded with a new method (OperationContract). I want to write a common method to handle the response from this new method as well as from the existing method at the endpoint.
I am trying to create a "Base" response class and adding common properties to it provided by the WCF endpoint, but I notice in my handler method, the properties are not being retained.
The code for the class I want all responses to inherit from looks like this :
public class ResponseBase
{
public string[] ItemsReturned;
public bool ItemsWereAvailable;
}
So I add partial declarations to get this onto the objects in the endpoint.
public partial class RetrieveResponse :ResponseBase
{
}
public partial class RetrieveResponse2 :ResponseBase
{
}
This way I have a handler method that just accepts "ResponseBase" as its input.
Am I doing this all wrong?
Any class whose instances will be return values and/or parameters of an operation contract should be decorated with the DataContract attribute, and the properties, as DataMembers:
[DataContract]
public class ResponseBase
{
[DataMember]
public string[] ItemsReturned { get; set; }
[DataMember]
public bool ItemsWereAvailable { get; set; }
}
http://msdn.microsoft.com/en-us/library/ms733127.aspx
If they are not, the DataContractSerializer doesn't serialize them.

Expose WCF service for derived class with same name in C#

I want to expose as WCF service two set of classes that have the same name. However, when I add the service reference, it only returns one set of the class.
[ServiceContract(Name = "Service1")]
[XmlSerializerFormat]
public interface IService1
{
[OperationContract]
[ServiceKnownType(typeof(S1.Retangle))]
[ServiceKnownType(typeof(S1.Square))]
[ServiceKnownType(typeof(S2.Retangle))]
[ServiceKnownType(typeof(S2.Square))]
string GetShape(Shape shape);
}
//All types are only example
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute()]
public abstract class Shape
{
public int Width { get; set; }
public int Height { get; set; }
public string TypeName { get; set; }
}
namespace S1
{
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute()]
public class Retangle : Shape
{ }
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute()]
public class Square : Shape
{ }
}
namespace S2
{
//[DataContract]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "Namespace=http://tempuri.org/S2")] //can be changed
public class Retangle : Shape
{ }
//[DataContract]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "Namespace=http://tempuri.org/S2")] //can be changed
public class Square : Shape
{ }
}
Any idea would be very much appreciated.
WCF will generate your objects in its own namespace for use client side but your not forced to use these - you can equally well use your own original objects in the namespaces they were defined by either:
1. Compiling them in a dll and linking to that for both client and sever.
2. If you dont want overhead of shared dll just compile them directly into both server and client.
In the generated proxy code you just need to replace the WCF namespace tags with your own org namespaces so they resolve to your objects and the client side WCF generated ones are ignored.