Expose particular fields in WCF - visual-studio-2010

I've a class
[DataContract]
public class Sample
{
[DataMember]
int a;
[DataMember]
int b;
[DataMember]
int c;
}
Sample sampleMethod1 ()
{
return new Sample { a =5, b=6 }
}
Sample sampleMethod1 ()
{
return new Sample { a =15, c=61 }
}
Now I want when my external customers call sampleMethod1 then the visible fields of sample class are a and c not b. similarly in sampleMethod2

you need something like this..
[DataContract]
[KnownType(typeof(SampleDerived1))]
[KnownType(typeof(SampleDerived2))]
public class Sample
{
[DataMember]
public int a;
}
[DataContract]
public class SampleDerived1 : Sample
{
[DataMember]
public int b;
}
[DataContract]
public class SampleDerived2 : Sample
{
[DataMember]
public int c;
}
and your methods should be like this..
Sample sampleMethod1 ()
{
return new SampleDerived1{ a =5, b=6 }
}
Sample sampleMethod2 ()
{
return new SampleDerived2{ a =15, c=61 }
}

Related

odata v4, List<> Property without expand

Is it possible in odata4 to create a model such as:
public class PuppyDogs
{
public string Name { get; set; }
public virtual IList<Bone> Bones { get; set; }
}
public class Bone
{
public string ChewType { get; set; }
public int Numberofchews { get; set; }
}
And the controller class looks like
public class PuppyDogController : ODataController
{
List<PuppysDog> mydogs = new List<PuppysDog>();
private PuppyDogController()
{
if (mydogs.Count == 0)
{
PuppysDog mydog = new PuppysDog();
mydog.Name = "Fido";
mydog.Bones = new List<Bone>()
{
new Bone{ ChewType = "Soft", Numberofchews=1 },
new Bone{ ChewType = "Hard", Numberofchews=2 }
};
mydogs.Add(mydog);
}
}
[EnableQuery]
public IQueryable<PuppysDog> Get()
{
return mydogs.AsQueryable();
}
}
Can I include the Bones property of PuppyDogs without using expand? By default Bones is not returned to the client.
There are several things nor clear in your code, for example, the entity set PuppyDogs don't have a key, the naming convention in the controller is a little wired and etc. With the following code, it can work perfectly, please take a look
PuppyDog.cs
public class PuppyDog
{
[Key]
public string Name { get; set; }
public virtual IList<Bone> Bones { get; set; }
}
Bone.cs
public class Bone
{
public string ChewType { get; set; }
public int Numberofchews { get; set; }
}
PupyyDogsController.cs
public class PuppyDogsController : ODataController
{
List<PuppyDog> mydogs = new List<PuppyDog>();
private PuppyDogsController()
{
if (mydogs.Count == 0)
{
PuppyDog mydog = new PuppyDog();
mydog.Name = "Fido";
mydog.Bones = new List<Bone>()
{
new Bone {ChewType = "Soft", Numberofchews = 1},
new Bone {ChewType = "Hard", Numberofchews = 2}
};
mydogs.Add(mydog);
}
}
[EnableQuery]
public IQueryable<PuppyDog> Get()
{
return mydogs.AsQueryable();
}
}
WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<PuppyDog>("PuppyDogs");
config.MapODataServiceRoute("odata", null, builder.GetEdmModel(), new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));
config.EnsureInitialized();
}
}
Then when try http://localhost:21830/PuppyDogs, I can successfully got the payload as
{
"#odata.context": "http://localhost:21830/$metadata#PuppyDogs",
"value": [
{
"Name": "Fido",
"Bones": [
{
"ChewType": "Soft",
"Numberofchews": 1
},
{
"ChewType": "Hard",
"Numberofchews": 2
}
]
}
]
}

LINQ query to get an object from nested collection

Suppose you have a collection of collection
Eg : CEO-> Vps-> GMs ->..
CEO will contain collection of VP's, VP's will have collection of GM's and so on.
Suppose you need to find a particular GM is the alias is given. Write a linq query to get the employee details if the employee alias is given.
You could try something like below
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
CeoCollection myCEOs = new CeoCollection();
var myGM = myCEOs.SelectMany(a => a.DummyVps.SelectMany(b => b.DummyGms.FindAll(c => c.Alias == "VeryDumb")));
}
}
public abstract class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public string Alias { get; set; }
}
public class CeoCollection : List<Ceo> { }
public class Ceo : Employee
{
public VpCollection DummyVps { get; set; }
}
public class VpCollection : List<Vp> { }
public class Vp : Employee
{
public GmCollection DummyGms { get; set; }
}
public class GmCollection : List<Gm> { }
public class Gm : Employee
{
}
}

How to post IEnumerable within a list to controller

I have a MVC3 app with the following model
public class Class1
{
public List<Class2> Class2Data { get; set; }
}
public class Class2
{
public int Id { get; set; }
public IEnumerable<Class3> Class3Data { get; set; }
}
public class Class3
{
public int Id { get set; }
public bool Selected { get; set; }
}
In my razor model
for (var i = 0; i < Model.Class2Data.Count();i++)
{
#Html.HiddenFor(c => c.Class2Data[i].Id)
foreach (var n in Model.Class2Data[i].Class3Data.ToList())
{
#Html.CheckBoxFor(x=> n.Selected);
#Html.HiddenFor(x=> n.Id);
}
}
However, when iam posting this to my controller, the Class3Data count is always 0 when I tick the checkboxes. Any ideas? Thanks
Resolved by changing IEnumerable to List as wasn't binding properly

entity framework programming against interface and repository pattern

I am developing in ASP.NET MVC3 and EntityFramework.
I want my model to follow an interface :
public class Account : IAccount
{
public string Id { get; set; }
public DateTime Date { get; set; }
public string Language { get; set; }
}
public interface IAccount
{
string Id { get; set; }
DateTime Date { get; set; }
string Language { get; set; }
}
Here's my Context
public class EFContext : DbContext, IContext
{
public DbSet<Account> Accounts { get; set; }
}
And here's the repository :
public interface IRepository<T> where T : class
{
IQueryable<T> All { get; }
int Count { get; }
bool Contains(Expression<Func<T, bool>> predicate);
void Create(T item);
void Update(T item);
void Delete(Expression<Func<T, bool>> predicate);
void Delete(T item);
}
public class EFRepository<T> : IRepository<T> where T : class
{
private EFContext _context;
public EFRepository(IUnitOfWork uow)
{
this._context = (EFContext)uow.Context;
}
protected DbSet<T> DbSet
{
get
{
return _context.Set<T>();
}
}
public IQueryable<T> All
{
get
{
return DbSet.AsQueryable();
}
}
public virtual int Count
{
get
{
return DbSet.Count();
}
}
public bool Contains(Expression<Func<T, bool>> predicate)
{
return DbSet.Count(predicate) > 0;
}
public virtual void Create(T item)
{
DbSet.Add(item);
}
public virtual void Update(T TObject)
{
var item = DbSet.Attach(TObject);
_context.SetItemState(TObject, EntityState.Modified);
}
public virtual void Delete(Expression<Func<T, bool>> predicate)
{
var objects = DbSet.Where(predicate);
foreach (var obj in objects)
{
DbSet.Remove(obj);
}
}
public virtual void Delete(T TObject)
{
DbSet.Remove(TObject);
}
}
Now, I want to use IRepository<IAccount> but this will ask the context for DbSet<IAccount>. This leads to an error since the Context contains a DbSet<Account>.
I then tried the solution proposed here for Linq2Sql : http://iridescence.no/post/Linq-to-Sql-Programming-Against-an-Interface-and-the-Repository-Pattern.aspx
So I added this function to my EFContext
public new DbSet<T> Set<T>() where T : class
{
var ciccio = TableMaps[typeof(T)];
return (DbSet<T>)base.Set(ciccio).Cast<T>();
}
But it doesn't work.
Do anyone have a suggestion?
Thx
What benefit are you receiving from using an interface for your entities? I don't see any value here. Typically, you use Interfaces to remove dependencies upon the implementation, but that's not what you're achieving here because you're returning a concrete DbSet of objects.
Your entities are already Poco's. They don't have dependencies on other implemntations, and they have no code in them other than a getter/setter. Using an interface is redundant and pointless.
I've found a workaround. I kind of like it so I want to share it.
I rewritten my EFRepository :
public class EFRepository<T, W> :
IRepository<T> where T : class
where W : class, T
{
private EFContext _context;
public EFRepository(IUnitOfWork uow)
{
this._context = (EFContext)uow.Context;
}
protected DbSet<W> DbSet
{
get
{
return _context.Set<W>();
}
}
public IQueryable<T> All
{
get
{
return DbSet.AsQueryable<T>();
}
}
public virtual int Count
{
get
{
return DbSet.Count();
}
}
public bool Contains(Expression<Func<T, bool>> predicate)
{
return All.Count(predicate) > 0;
}
public virtual void Create(T item)
{
DbSet.Add(item as W);
}
public virtual void Update(T TObject)
{
var item = DbSet.Attach(TObject as W);
_context.SetItemState(TObject, EntityState.Modified);
}
public virtual void Delete(Expression<Func<T, bool>> predicate)
{
var objects = All.Where(predicate);
foreach (var obj in objects)
{
DbSet.Remove(obj as W);
}
}
public virtual void Delete(T TObject)
{
DbSet.Remove(TObject as W);
}
}
So now basically all I need to do now is
IRepository<IAccount>> accRepository = new EFRepository<IAccount, Account>(uow);
I am happy with this solution, but still I'm not sure it is the best one, so any comments will be appreciated.
Thanks

Concrete implementation of generic base class and extension method

The end goal for this post is to override the ToString() method of a concrete implementation of a generic base class while still being able to search the implementation using Linq flattening technique. So if you read this and see a better way let me know. I'm using Telerik controls for Silverlight and they won't change their api to allow some of their control properties to be data-bound and instead rely on the ToString() method of whatever object they are bound to. yea, stupid.. Anyway here is what I've got.
RadTreeView control on my page. The FullPath property of each node in the treeview uses the ToString() method of each item its bound to (so this is what I need to override).
I had to create an "intermediary" class to enhance my base model class so it can be bound as a heirarchy in the tree view and then a concrete implementation of that generic class to override ToString(). Now the problem is I have a Linq extension that explodes because it cannot convert the concrete implementation back to the base generic class. I love generics but this is too much for me. Need help on solving the extension method issue.
Intermediary generic class:
public class HeirarchicalItem<T> : NotifyPropertyChangedBase, INotifyCollectionChanged where T : class
{
public event NotifyCollectionChangedEventHandler CollectionChanged;
public virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs ea)
{
if (CollectionChanged != null)
CollectionChanged(this, ea);
}
public HeirarchicalItem() { }
public HeirarchicalItem(T item)
{
Item = item;
}
public HeirarchicalItem(IEnumerable<T> collection)
{
CopyFrom(collection);
}
private T _item;
public T Item
{
get
{
return _item;
}
set
{
_item = value;
RaisePropertyChanged<HeirarchicalItem<T>>(a => a.Item);
}
}
private ObservableCollection<HeirarchicalItem<T>> _children = new ObservableCollection<HeirarchicalItem<T>>();
public virtual ObservableCollection<HeirarchicalItem<T>> Children
{
get { return _children; }
set
{
_children = value;
RaisePropertyChanged<HeirarchicalItem<T>>(a => a.Children);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
private void CopyFrom(IEnumerable<T> collection)
{
if ((collection != null))
{
using (IEnumerator<T> enumerator = collection.GetEnumerator())
{
while (enumerator.MoveNext())
{
HeirarchicalItem<T> newHeirarchicalItem = new HeirarchicalItem<T>(enumerator.Current);
Children.Add(newHeirarchicalItem);
RaisePropertyChanged<HeirarchicalItem<T>>(a => a.Children);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));
}
}
}
}
}
Base model class: (data is shuttled to and from WCF Ria service using this class)
public class tbl_Path : EntityBase, IFullPath, IEquatable<tbl_Path>, IEqualityComparer<tbl_Path>
{
public tbl_Path();
public int GetHashCode(tbl_Path obj);
public override string ToString();
public DateTime CreateDate { get; set; }
public short Depth { get; set; }
public string FullPath { get; set; }
public bool IsAuthorized { get; set; }
public bool IsSelected { get; set; }
public string Name { get; set; }
public override IEnumerable<Operation> Operations { get; }
public int? ParentPathID { get; set; }
public int PathID { get; set; }
public Guid SecurityKey { get; set; }
public EntityCollection<tbl_Configuration> tbl_Configuration { get; set; }
public EntityCollection<tbl_Key> tbl_Key { get; set; }
public EntityCollection<tbl_SecurityACL> tbl_SecurityACL { get; set; }
public EntityCollection<tbl_SecurityInheriting> tbl_SecurityInheriting { get; set; }
public EntityCollection<tbl_Variable> tbl_Variable { get; set; }
}
Concrete Implementation so that I can override ToString():
public class HeirarchicalPath : HeirarchicalItem<tbl_Path>
{
public HeirarchicalPath()
{
}
public HeirarchicalPath(tbl_Path item)
: base(item)
{
}
public HeirarchicalPath(IEnumerable<tbl_Path> collection)
: base(collection)
{
}
public override string ToString()
{
return Item.Name; **// we override here so Telerik is happy**
}
}
And finally here is the Linq extension method that explodes during compile time because I introduced a concrete implementation of my generic base class.
public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> fnRecurse)
{
foreach (T item in source)
{
yield return item;
IEnumerable<T> seqRecurse = fnRecurse(item);
if (seqRecurse != null)
{
foreach (T itemRecurse in Traverse(seqRecurse, fnRecurse))
{
yield return itemRecurse;
}
}
}
}
Actual code that is breaking: (x.Children is highlighted with the error)
Cannot implicitly convert type
'System.Collections.ObjectModel.ObservableCollection<HeirarchicalItem<tbl_Path>>' to
'System.Collections.Generic.IEnumerable<HeirarchicalPath>'. An explicit conversion
exists (are you missing a cast?)
HeirarchicalPath currentItem = this.Paths.Traverse(x => x.Children).Where(x => x.Item.FullPath == "$/MyFolder/Hello").FirstOrDefault();
Figured it out. Been working on this all day and minutes after posting the question I resolve it as always.
Just needed to add this bit to my concrete implementation and no more compiler errors.
private ObservableCollection<HeirarchicalPath> _children = new ObservableCollection<HeirarchicalPath>();
public new ObservableCollection<HeirarchicalPath> Children
{
get
{
return _children;
}
set
{
if (value == null)
return;
_children = value;
RaisePropertyChanged<HeirarchicalPath>(a => a.Children);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}

Resources