wcf generic datacontract does not get serialized - wcf

I am having the following data structure:
[DataContract]
public class OperationResult<T>
{
public OperationResult() { }
[DataMember]
public Int32 OpResult
{
get;set;
}
[DataMember]
public IList<T> OperationResults
{
get;set;
}
public static OperationResult<T> Success(IList<T> results, int numberOfChangedObjects)
{
OperationResult<T> result = new OperationResult<T>();
result.OpResult = 1;
result.OperationResults = results;
return result;
}
}
When I update the service reference, the class does not get serialized. In the service I am using a so-called closed generic type
eg.
[OperationContract]
public OperationResult<Int32> SometTestMethod()
{
return new OperationResult<Int32>
{
OpResult = 1,
OperationResults = new List<Int32> {1, 2, 3}
};
}
The method is exposed, but the return type OperationResult in this case is not accesible.
What am I doing wrog?
Thanks

I just realized. The reason I didn't find the type is because I was looking for an OperationResult. As it got serialized , it was named OperationResultOfInt.

Related

Return Entity Framework objects over WCF

We have a problem concerning Entity Framework objects and sending them through WCF.
We have a database, and Entity Framework created classes from that database, a 'Wallet' class in this particular situation.
We try to transfer a Wallet using this code:
public Wallet getWallet()
{
Wallet w = new Wallet();
w.name = "myname";
w.walletID = 123;
return w;
}
We need to transfer that Wallet class, but it won't work, we always encounter the same exception:
"An error occurred while receiving the HTTP response to localhost:8860/ComplementaryCoins.svc. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details."
We searched on the internet, and there is a possibility that the error is due to the need of serialization of Entity Framework-objects.
We have absolutely no idea if this could be the case, and if this is the case, how to solve it.
Our DataContract looks like this (very simple):
[DataContract]
public partial class Wallet
{
[DataMember]
public int getwalletID { get { return walletID; } }
[DataMember]
public string getname { get { return name; } }
}
Does anyone ever encountered this problem?
EDIT: Our Entity Framework created class looks like this:
namespace ComplementaryCoins
{
using System;
using System.Collections.Generic;
public partial class Wallet
{
public Wallet()
{
this.Transaction = new HashSet<Transaction>();
this.Transaction1 = new HashSet<Transaction>();
this.User_Wallet = new HashSet<User_Wallet>();
this.Wallet_Item = new HashSet<Wallet_Item>();
}
public int walletID { get; set; }
public string name { get; set; }
public virtual ICollection<Transaction> Transaction { get; set; }
public virtual ICollection<Transaction> Transaction1 { get; set; }
public virtual ICollection<User_Wallet> User_Wallet { get; set; }
public virtual ICollection<Wallet_Item> Wallet_Item { get; set; }
}
}
Thanks for helping us.
I had the same problem some time ago and the solution for this was:
The entity framework was returning a serialized class instead of normal class.
eg. Wallet_asfawfklnaewfklawlfkawlfjlwfejlkef instead of Wallet
To solve that you can add this code:
base.Configuration.ProxyCreationEnabled = false;
in your Context file.
Since the context file is auto generated you can add it in the Context.tt
In the Context.tt file it can be added around lines 55-65:
<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{
public <#=code.Escape(container)#>()
: base("name=<#=container.Name#>")
{
base.Configuration.ProxyCreationEnabled = false;
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
this.Configuration.LazyLoadingEnabled = false;
<#
Try specifying a setter for the properties, something like this :
[DataContract]
public partial class Wallet
{
[DataMember]
public int getwalletID { get { return walletID; } set { } }
[DataMember]
public string getname { get { return name; } set { } }
}
If it still doesn't work, you may consider creating an intermediate POCO class for this purpose, and use mapper library like AutoMapper or ValueInjecter to transfer the data from the EF objects.
The POCO class should have same properties as your EF class :
[DataContract]
public class WalletDTO
{
[DataMember]
public int walletID { get; set; }
[DataMember]
public string name { get; set; }
}
And modify your method to return this class instead :
public WalletDTO getWallet()
{
Wallet w = new Wallet(); // or get it from db using EF
var dto = new WalletDTO();
//assuming we are using ValueInjecter, this code below will transfer all matched properties from w to dto
dto.InjectFrom(w);
return dto;
}
Are you trying to recieve a IEnumerable<Wallets>? If - yes, please modify your server class that returns the IEnumerable by adding .ToArray() method

Using a datamember type of list

i'm new with wcf and i create a DataContract like this :
[DataContract]
public class directoriesUser
{
[DataMember]
public string NameDir { get; set; }
[DataMember]
public directoriesUser Parent { get; set; }
private ObservableCollection<directoriesUser> _userDirs = new ObservableCollection<directoriesUser>();
[DataMember]
public ObservableCollection<directoriesUser> UserDirectories
{
get { return _userDirs; }
set { _userDirs = value; }
}
}
But whe i use this class like above, the service throw an exception. can someone help me ?
public directoriesUser getHomeUser(int user_id)
{
directoriesUser dirhome = new directoriesUser();
// this doesn't works
dirhome.UserDirectories = new ObservableCollection<directoriesUser>{
new directoriesUser { NameDir = "dir1", Parent = dirhome},
new directoriesUser {NameDir = "dir2", Parent = dirhome}
};
// neither this one
dirhome.UserDirectories.Add(new directoriesUser {NameDir = "dir3", Parent = dirhome})
return dirhome;
}
Your directoriesUser class probably causes recursion when wcf serializes the instance. This is basically caused by the Parent property pointing back up the hierarchy.
Here's a more detailed article about this.

Context variables in Ninject 2

I found this article on Context Variables in an earlier version of Ninject. My question is two-fold. First, how can I get this behavior with Ninject 2? Secondly, do context variables carry through down the request chain? For example, let's say I wanted to replace these calls:
var a = new A(new B(new C())));
var specialA = new A(new B(new SpecialC()));
... with this:
var a = kernel.Get<A>();
var specialA = kernel.Get<A>(With.Parameters.ContextVariable("special", "true"));
Is it possible to set up a binding like this, where the context remembers that it is in a "special" context when it comes time to construct a C?
Here's some stuff that I use against V2, with ~0 effort to clean it up for you - let me know if you can't disentagle it.
As you surmised, there doesn't seem to be a really explicit API that surfaces the "context parameter, even for nested resolutions" stuff in v2 as-is (it's presence is buried as the 3rd parameter on an overload of the Parameter ctor).
public static class ContextParameter
{
public static Parameter Create<T>( T value )
{
return new Parameter( value.GetType().FullName, value, true );
}
}
public static class ContextParameterFacts
{
public class ProductId
{
public ProductId( string productId2 )
{
Value = productId2;
}
public string Value { get; set; }
}
public class Repository
{
public Repository( ProductId productId )
{
ProductId = productId;
}
public ProductId ProductId { get; set; }
}
public class Outer
{
public Outer( Repository repository )
{
Repository = repository;
}
public Repository Repository { get; set; }
}
public class Module : NinjectModule
{
public override void Load()
{
Bind<ProductId>().ToContextParameter();
}
}
//[ Fact ]
public static void TwoDeepShouldResolve()
{
var k = new StandardKernel( new Module() );
var o = k.Get<Outer>( ContextParameter.Create( new ProductId( "a" ) ) );
Debug.Assert( "a" == o.Repository.ProductId.Value );
}
}
And here's some code [that'll confuse the matter] which demonstrates how I apply it in my context:-
public class ServicesNinjectModule : NinjectModule
{
public override void Load()
{
Bind<ProductId>().ToContextParameter();
Bind<Func<ProductId, ResourceAllocator>>().ToConstant( ( productId ) => Kernel.Get<ResourceAllocator>(
ContextParameter.Create( productId ) ) );
}
}
public static class NinjectContextParameterExtensions
{
public static IBindingWhenInNamedWithOrOnSyntax<T> ToContextParameter<T>( this IBindingToSyntax<T> bindingToSyntax )
{
return bindingToSyntax.ToMethod( context => (T)context.Parameters.Single( parameter => parameter.Name == typeof( T ).FullName ).GetValue( context ) );
}
}
As usual, you should go look a the source and the tests - they'll provide you with a far more detailed and relevant answer than I can.

Multi-tier applications using L2S, WCF and Base Class

One day I decided to build this nice multi-tier application using L2S and WCF.
The simplified model is : DataBase->L2S->Wrapper(DTO)->Client Application.
The communication between Client and Database is achieved by using Data Transfer Objects which contain entity objects as their properties.
abstract public class BaseObject
{
public virtual IccSystem.iccObjectTypes ObjectICC_Type
{
get { return IccSystem.iccObjectTypes.unknownType; }
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage = "_ID", AutoSync = AutoSync.OnInsert, DbType = "BigInt NOT NULL IDENTITY", IsPrimaryKey = true, IsDbGenerated = true)]
[global::System.Runtime.Serialization.DataMemberAttribute(Order = 1)]
public virtual long ID
{
//get;
//set;
get
{
return _ID;
}
set
{
_ID = value;
}
}
}
[DataContract]
public class BaseObjectWrapper<T> where T : BaseObject
{
#region Fields
private T _DBObject;
#endregion
#region Properties
[DataMember]
public T Entity
{
get { return _DBObject; }
set { _DBObject = value; }
}
#endregion
}
Pretty simple, isn't it?. Here's the catch. Each one of the mapped classes contains ID property itself so I decided to override it like this
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Divisions")]
[global::System.Runtime.Serialization.DataContractAttribute()]
public partial class Division : INotifyPropertyChanging, INotifyPropertyChanged
{
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ID", AutoSync=AutoSync.OnInsert, DbType="BigInt NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
[global::System.Runtime.Serialization.DataMemberAttribute(Order=1)]
public override long ID
{
get
{
return this._ID;
}
set
{
if ((this._ID != value))
{
this.OnIDChanging(value);
this.SendPropertyChanging();
this._ID = value;
this.SendPropertyChanged("ID");
this.OnIDChanged();
}
}
}
}
Wrapper for division is pretty straightforward as well:
public class DivisionWrapper : BaseObjectWrapper<Division>
{
}
It worked pretty well as long as I kept ID values at mapped class and its BaseObject class the same(that's not very good approach, I know, but still) but then this happened:
private CentralDC _dc;
public bool UpdateDivision(ref DivisionWrapper division)
{
DivisionWrapper tempWrapper = division;
if (division.Entity == null)
{
return false;
}
try
{
Table<Division> table = _dc.Divisions;
var q = table.Where(o => o.ID == tempWrapper.Entity.ID);
if (q.Count() == 0)
{
division.Entity._errorMessage = "Unable to locate entity with id " + division.Entity.ID.ToString();
return false;
}
var realEntity = q.First();
realEntity = division.Entity;
_dc.SubmitChanges();
return true;
}
catch (Exception ex)
{
division.Entity._errorMessage = ex.Message;
return false;
}
}
When trying to enumerate over the in-memory query the following exception occurred:
Class member BaseObject.ID is unmapped.
Although I'm stating the type and overriding the ID property L2S fails to work.
Any suggestions?
Suppose I found the problem.
When writing
var q = table.Where(o => o.ID == tempWrapper.Entity.ID);
the compiler implies that the object is of BaseObject type and therefore tries to get its ID value from the BaseObject mapping and it's unmapped.
The problem seems to be resolved by explicitly declaring the type:
var q = from Division div in _dc.GetTable<Division>()
where div.ID == tempWrapper.Entity.ID
select div;

Custom datacontract / datamember name

I have a following problem. A customer requested a web service that returns data in following format:
<status>
<name1>Some name</name1>
...
</status>
But when an error occurs they want to get a following message:
<status>
<error>Error description</error>
</status>
I created a web service using WCF and in order to fulfill the requirements I defined a following service contract:
[ServiceContract]
public interface IPatronStatus
{
[OperationContract]
[ServiceKnownType("GetKnownTypes", typeof(KnownTypesProvider))]
[WebGet(UriTemplate = "/service/status?user={unilogin}")]
StatusData GetPatronStatus(string unilogin);
}
And also defined a following base class:
[DataContract(Name="status")]
public class StatusData
{
}
And two derrived classes:
public class PatronStatusData : StatusData
{
private string _name;
[DataMember(Name = "name1", Order = 0)]
public string Name
{
get { return _name; }
set { _name = value; }
}
...
}
And:
public class UniLoginNotFoundError : StatusData
{
public UniLoginNotFoundError()
{ }
private string _description = "UniLoginNotFoundError";
[DataMember(Name = "error", Order = 0)]
public string Description
{
get
{
return _description;
}
}
}
The problem is that when I pull the data from the web service the data contract name ("status") and the names of the data members are ignored and the type's and properties' names are used.
Is it possible to use the custome names?
You should decorate both UniLoginNotFoundError and PatronStatusData with DataContract(Name="Something") to make this work. But you won't be allowed to set the same name ("status") for them.
In your particular case I'd better use single class with unused properties set to null.
[DataContract(Name="status")]
public class StatusData
{
private string _name;
private string _errorDescription = null;
[DataMember(Name = "name1", Order = 0, EmitDefaultValue=false)]
public string Name
{
get { return _name; }
set { _name = value; }
}
[DataMember(Name = "error", Order = 1, EmitDefaultValue=false)]
public string Description
{
get{ return _errorDescription ;}
set {_errorDescription =value ;}
}
...
}
Generally speaking, it's a mistake to want too much control over the XML generated by serializing a Data Contract. That's the trap of the XML Serializer. Define the contract in general terms, and have the clients just consume the result, which will generally be simple enough.